CSDN APP 中H5页面,有部分链接的跳转是需要拦截,并且用新页面的方式打开。
WKWebView 中提供了以下方法,供我们使用。
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences * _Nonnull))decisionHandler
{
if (判断是否需要跳转){
//跳转的逻辑
decisionHandler(WKNavigationActionPolicyCancel,preferences);
}else{
decisionHandler(WKNavigationActionPolicyAllow,preferences);
}
}
一般我们判断用户是否是点击链接,直接用WKNavigationType
来判断,它有以下枚举状态
typedef NS_ENUM(NSInteger, WKNavigationType) {
WKNavigationTypeLinkActivated,//链接的href属性被用户激活。
WKNavigationTypeFormSubmitted,//一个表单提交。
WKNavigationTypeBackForward,//回到前面的条目列表请求。
WKNavigationTypeReload,//网页加载。
WKNavigationTypeFormResubmitted,//一个表单提交(例如通过前进,后退,或重新加载)。
WKNavigationTypeOther = -1,//导航是发生一些其他原因。
} NS_ENUM_AVAILABLE(10_10, 8_0);
当navigationAction.navigationType == WKNavigationTypeLinkActivated
时,可以知道,这次跳转是点击链接跳转。
但是,我们在使用中发现,很多跳转中navigationAction.navigationType == WKNavigationTypeOther
,这时,我们的判断就不会生效。
如下图:我们需要的是跳转新页面,并不是当前页面刷新。
1、首先,我们通过原生是无法拿到判断状态是点击跳转还是主动reload,那我们就通过用JS监听点击事件的方式,来获取用户是否有点击页面的操作。如果用户有点击操作,那就通过window.webkit.messageHandlers
与原生通信,告诉原生页面有点击事件操作。
/// 监听用户有没有点击页面
-(NSString *)setJSTouchString{
NSString *touchJs = @"\
document.addEventListener('touchstart',e => {\
this.move = false;\
this.start = e.changedTouches[0].pageY;\
});\
document.addEventListener('touchmove',e => {\
this.move = true;\
});\
document.addEventListener('touchend',e => {\
this.end = e.changedTouches[0].pageY;\
if(!this.move){\
window.webkit.messageHandlers.TouchEvent.postMessage(true);\
}else{\
window.webkit.messageHandlers.TouchEvent.postMessage(false);\
}\
});\
";
return touchJs;
}
2、原生通过- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
获取到用户点击状态
// MARK: - js调用原生方法 可在此方法中获得传递回来的参数
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if([message.name isEqualToString:@"TouchEvent"]){
self.isTouchWeb = [message.body boolValue];
}
}
3、提供以下方法,来判断是否是点击链接跳转
/// 返回给定的导航是否由用户链接单击触发
/// @param navigationType
- (BOOL)isLinkNavigation:(WKNavigationType)navigationType {
switch (navigationType) {
case WKNavigationTypeLinkActivated:
return YES;
case WKNavigationTypeOther:
return self.isTouchWeb;
default:
return NO;
}
}
这样,就解决了无法判断用户是否是点击链接的问题。最后实现的效果如下图:
需要注意的是,如果WKWebView有下拉刷新或者双击Tab刷新功能的话,需要在刷新前将点击状态重置。即
self.isTouchWeb = NO