• iOS WKWebView 判断跳转链接是否是用户点击


    背景

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    一般我们判断用户是否是点击链接,直接用WKNavigationType来判断,它有以下枚举状态

    typedef NS_ENUM(NSInteger, WKNavigationType) {
        WKNavigationTypeLinkActivated,//链接的href属性被用户激活。
        WKNavigationTypeFormSubmitted,//一个表单提交。
        WKNavigationTypeBackForward,//回到前面的条目列表请求。
        WKNavigationTypeReload,//网页加载。
        WKNavigationTypeFormResubmitted,//一个表单提交(例如通过前进,后退,或重新加载)。
        WKNavigationTypeOther = -1,//导航是发生一些其他原因。
    } NS_ENUM_AVAILABLE(10_10, 8_0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、提供以下方法,来判断是否是点击链接跳转

    /// 返回给定的导航是否由用户链接单击触发
    /// @param navigationType
    - (BOOL)isLinkNavigation:(WKNavigationType)navigationType {
      switch (navigationType) {
        case WKNavigationTypeLinkActivated:
          return YES;
        case WKNavigationTypeOther:
          return self.isTouchWeb;
        default:
          return NO;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这样,就解决了无法判断用户是否是点击链接的问题。最后实现的效果如下图:
    请添加图片描述

    需要注意的是,如果WKWebView有下拉刷新或者双击Tab刷新功能的话,需要在刷新前将点击状态重置。即self.isTouchWeb = NO

  • 相关阅读:
    【KOS】安装卸载软件
    mysql的行锁和间隙锁
    树莓派 3b+ 没有 /dev/i2c-*
    数据宝荣获“2021-2022年度最具影响力数字化转型服务商”称号
    Flux、Atomic、Proxy 不同心智模型状态管理库的比较和原理
    FPGA实现HDMI输入转SDI视频输出,提供4套工程源码和技术支持
    【纯css】实现无限滚动循环组件,无js
    YOLOv8_obb预测流程-原理解析[旋转目标检测理论篇]
    螺丝扭断力试验机SJ-12
    继承、抽象类、代码块
  • 原文地址:https://blog.csdn.net/weixin_36162680/article/details/126441975