swift - WKWebView api功能分析

27 篇文章 0 订阅

WKWebView

参考文章
(https://github.com/wszxy/WKWebViewCookie/tree/7861c27af73ba8522dca36cc0dee218d133ba0da)

工程文件
https://www.dropbox.com/sh/qghyu9xho6cgqfl/AAAf0QMjnGnJXhGAFYfLSXnAa?dl=0

关于H5页面的问题我不是很懂的,JS的大部分我都是问大学舍友完成

WKWebViewConfiguration

用户代理字符串中使用的应用程序的名称 (不明白)

open var applicationNameForUserAgent: String?

webConfiguration.applicationNameForUserAgent = "123"

默认为**(“Mobile/15E148”)** 更改后**(“123”)**

是否使用JavaScript,默认是使用的

        // 是否启用javaScript,默认是YES
//        webConfiguration.preferences.javaScriptEnabled = false
        // ios 14以上使用这个
        let preference = WKWebpagePreferences()
        preference.allowsContentJavaScript = false
        webConfiguration.defaultWebpagePreferences = preference

截屏2022-01-26 上午11.34.02

配置为同一个进程池的WebView会共享数据,例如Cookie、用户凭证等,开发者可以通过编写管理类来分配不同维度的WebView在不同进程池中。

open var processPool: WKProcessPool
webConfiguration.processPool = WKProcessPool()

交互

// 注入js对象名称为xxxx,当js通过xxxx来调用
        // 可以在wkscriptMessagehandler的代理中接收到
        webConfiguration.userContentController.add(self,name: "xxxx")
WKNavigationDelegate

此代理实现的方法可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。

wkWebView.navigationDelegate = self
WKUIDelegate

**与界面弹出提示框相关的代理方法,针对于web界面的三种提示框(警告框、确认框、输入框)分别对应三种代理方法。 **

wkWebView.uiDelegate = self
cookie的验证

20220124153039

20220124153039

本地localhost配置

1.开启Apache 打开terminal,输入sudo apachectl start,打开浏览器,输入localhost或127.0.0.1,显示it works!说明服务器开启成功

2.配置php 找到php的配置文件的路径:/etc/apache2/httpd.conf 用记事本打开,搜索定位到php7_module这句话,然后将前面的#去掉,保存退出。

3.重启Apache 在terminal中输入:sudo apachectl restart 再次用浏览器访问localhost/index.php,当你看到it works!显示说明配置成功了。

4.客户端设置 这里的客户端指的是iOS设备,只要客户端与服务器处在同一个局域网下,就可以直接通过ip地址访问。ip地址通过打开网络偏好设置查看。

如果不能保存退出的话,说什么没有权限允许,可以终端输入 vim /etc/apache2/httpd.conf 进行终端修改

D6DBFC6B-9865-413F-9ECC-3D393B11AF64

清理磁盘:清理了library目录下的cookie文件
清理内存:清理NSHTTPCookieStorage的cookie数组,是模拟进程退出的情况
新建(普通):新建一个WKWebView,并发送请求
新建(带Script):区别于普通的新建,新建WKWebView的时候,会在configuration中通过userScript的方式设置cookie,cookie的name为name_test,value为Config setting
刷新:页面刷新,不涉及新建,重新发送请求。

首次进来时,php读取不到cookie,而js读取一直成功,即使是第一次访问页面。

也就是优先读取客户端请求里的cookie,读不到时会读取服务器设置的cookie。

截屏2022-01-24 下午3.51.25

点击刷新后,php读取到cookie。

证明了:首次请求没有cookie,响应回来后设置,后续的请求就会带上cookie,可以说明在这种刷新的情况下,WKWebView请求是会自动带上cookie的

截屏2022-01-24 下午3.55.31

当清理磁盘和清理内存,cookie有时读不到。当cookie已经生成时,新建WKWebView不影响cookie的读取,而一旦清理了磁盘时,cookie就没有了。而清理内存,内存里的内容来自于读取磁盘里的内容,有时可以读取的到。

新建(带script)方式

userScript是设置在configuration里,而configuration作为参数初始化WKWebView,每次新建就相当于一个新的设置,这种方式的cookie存储和WKWebView的生命周期绑定了,同生共灭。

let config = WKWebViewConfiguration()
        config.preferences = WKPreferences()
        config.preferences.minimumFontSize = 20
        config.preferences.javaScriptCanOpenWindowsAutomatically = false
        let userController = config.userContentController
        let cookieSource = "document.cookie = 'name_test=Config setting';"
        let cookieScript = WKUserScript.init(source: cookieSource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
        userController.addUserScript(cookieScript)
WKWebView拦截器 (WKNavigationDelegate方法实现)

截屏2022-01-26 上午11.34.02

WKNavigationDelegate里的,其中jsToSwift就是标识字段。

通过URL进行拦截,也就是请求的时候拦截

// 拦截url
 func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        print("在请求开始加载之前调用,决定是否跳转=====\(navigationAction.request.url?.absoluteString ?? "")")
        if navigationAction.request.url?.scheme?.caseInsensitiveCompare("jsToSwift") == ComparisonResult.orderedSame {
            print("*********************")
            print(navigationAction.request.url?.query)
            print(navigationAction.request.url?.host)
            decisionHandler(.cancel)
        }else {
            decisionHandler(WKNavigationActionPolicy.allow)
        }
        
        
    }

打印的字段为

在请求开始加载之前调用,决定是否跳转=====jstoswift://loginSucceed?js_tokenString

Optional(“js_tokenString”)

Optional(“loginSucceed”)

javaScript代码

//! 加载URL
            function loadURL(url) {
                window.location.href = url;
            }
        
            //! JS调用swift入口
            function jsToSwift(action, params) {
                var url = "jsToSwift://" + action + "?" + params;
                loadURL(url);
            }
            
            //! JS登录成功后loadURL并传参token
            function loginSucceed(token) {
                var action = "loginSucceed";
                jsToSwift(action, token);
            }
            
            //! JS调用swift的登录功能
            function login() {
                var token = "js_tokenString";
                loginSucceed(token);
            }

H5代码显示

<button onclick = "login()" style = "font-size: 18px;">登录</button>
JS调用原生方法(WKScriptMessageHandler实现)

原生中注册方法给JS使用

        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "openCamera")
        config.userContentController.add(self, name: "playVideo")
        self.webView = WKWebView.init(frame: CGRect(x: 0, y: 200, width: 200, height: 200),configuration: config)

JS使用注册的方法传值

            function useCamera() {
                window.webkit.messageHandlers.openCamera.postMessage(null);
            }
            function useVideo(vedio) {
                var obj = {"name":"God", "Author":"Jhon Trank"};
                window.webkit.messageHandlers.playVideo.postMessage(obj);
            }

window.webkit.messageHandlers.<方法名字>.postMessage

其中add()第一个参数是WKScriptMessageHandlerdelegate,该代理只有一个函数userContentController负责管理js的传值

iOS接收

    //js向swift传值
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "openCamera" {
            print(message.name)
            print(message.body)
        }else if message.name == "playVideo" {
            print(message.name)
            print(message.body)
        }
    }   
    
原生调用JS方法
self.webView.evaluateJavaScript("jsToSwift('loginSucceed', 'oc_tokenString')") { response, error in
            print("response:\(response)")
 }

js的实现方法,实现方法为一个URL请求,原生进行截断

//! JS调用OC入口
            function jsToSwift(action, params) {
                var url = "jsToSwift://" + action + "?" + params;
                loadURL(url);
            }
警告弹窗使用(WKUIDelegate)

如果不封装的话,js调用的alert confirm设备是不会显示的,所以需要使用到WKUIDelegate监听JS调用的弹窗

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现 JSBridge 的关键是在原生的 WKWebView 中添加 JavaScript,使之能够被调用并处理传递的数据。以下是一个简单的 Swift 版本的实现: 1. 在原生代码中添加 JavaScript ```swift // WKWebView 初始化 let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration()) // 注入 JavaScript 脚本 let jsScript = "window.webkit.messageHandlers.jsBridge.postMessage" let userScript = WKUserScript(source: jsScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false) webView.configuration.userContentController.addUserScript(userScript) // 添加消息处理器 webView.configuration.userContentController.add(self, name: "jsBridge") ``` 2. 实现 WKScriptMessageHandler 协议 使用 WKScriptMessageHandler 协议来接收从 JavaScript 中传递的消息。在 Swift 中,需要使用 `@objc` 来声明方法。 ```swift extension ViewController: WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "jsBridge" { // 处理传递的数据 let data = message.body as? [String: Any] // ... } } } ``` 3. 在 JavaScript 中实现调用 在 JavaScript 中使用 `window.webkit.messageHandlers.jsBridge.postMessage(data)` 来将数据传递给原生代码。以下是一个示例: ```javascript // 发送数据给原生代码 window.webkit.messageHandlers.jsBridge.postMessage({ action: "showAlert", data: { message: "Hello from JavaScript!" } }); ``` 通过以上步骤,就可以在 Swift 中实现一个简单的 JSBridge。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值