• 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

  • 相关阅读:
    第三章:最新版零基础学习 PYTHON 教程(第十三节 - Python 运算符—Python 中的运算符函数 - 套装2)
    Servlet系列:基于 XML 和 注解的方式配置 Servlet 以及封装 BaseServlet
    数据结构——时间复杂度与空间复杂度
    Spring Boot入门(22):【Spring Boot+LogBack】高效记录日志,实现日志文件本地化保存!
    基于IMDB评论数据集的情感分析
    【算法|动态规划No.26】leetcode1745. 分割回文串 IV
    Java八大排序算法
    JavaScript基本语法详解
    【大数据入门核心技术-Hadoop】Hadoop高可用集群搭建
    软考 系统架构设计师之回归及知识点回顾(3)
  • 原文地址:https://blog.csdn.net/weixin_36162680/article/details/126441975