美文网首页
1.WebView与OC通讯方式

1.WebView与OC通讯方式

作者: 你weixiao的时候很美 | 来源:发表于2019-01-18 13:33 被阅读25次

参考:
WK 与 JS 的那些事 WKWebView使用
H5 与 Native 交互之 JSBridge 技术

1.简介

从iOS12开始,苹果正式废弃UIWebView,使用WKWebView。使用WebView的主要问题是原生OC如何与webView通讯的问题,即 js与oc的如何交互。

UIWebView与WKWebView比较:
1.内存占用,加载速度wkwebview有优势.
2.wkwebview将协议和类拆分,更清晰.
3.wkwebview带有进度属性estimatedProgress.
4.wkwebview不支持页面缓存,需要自己注入cookie,而uiwebview是自动注入cookie.
5.wkwebview无法使用jscontext.

2. 原理

1.使用原生调用js
其实就是调用了window下的一个对象,如果我们要让native来调用我们js写的方法,那这个方法就要在window下能访问到.

2.使用js调用原生oc
在webView内发起网络请求都可以被原生拦截.

我们发起一个自定义的网络请求,通常格式: jsbridge://methodName?param1=value1&param2=value2. 发现是jsbridge://开头的地址,就不进行内容的加载,转而执行相应的调用逻辑

发起这样一个网络请求有两种方式:1. 通过localtion.href;2. 通过iframe方式. 我们通过设置一个隐藏的ifrmame来达到发送自定义请求的目的.

3.交互方式:
使用WKWebview时,原生oc与js交互的主要思想是拦截。有一下几种方式:

  1. 直接拦截js的url跳转。
  2. 使用messageHandle。
  3. 使用三方如WebViewJavaScriptBridge
3.直接拦截js的响应方法。

1.js告诉oc要跳转
WKWebView实现WKNavigationDelegate,当js跳转的时候,代理会实现

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    //根据navigationAction.request 可以拦截每一个js执行的超链接。
    decisionHandler(WKNavigationActionPolicyAllow);
}

顺便说一下,WKNavigationDelegate是webView页面跳转时候的代理:

#pragma mark - WKNavigationDelegate
//请求之前,决定是否要跳转:用户点击网页上的链接,需要打开新页面时,将先调用这个方法。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
//接收到相应数据后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
//页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation;
// 主机地址被重定向时调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation;
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation;
// 页面加载完毕时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation;
//跳转失败时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;
// 如果需要证书验证,与使用AFN进行HTTPS证书验证是一样的
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler;
//9.0才能使用,web内容处理中断时会触发
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0);

2.OC告诉js执行方法

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler

//webview 调用该方法使js执行 javaScriptString的代码。
4. 使用messageHandler

1.js调用oc(js给oc发消息)

1.实现方式
WKWebview原生通过实现userContentController类添加MessageHandler实现。

    1. 设置userContentController的代理
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"JSMessageToOC"];
  • 2.在js中,当需要给oc发消息的时候执行如下,这样是为了和安卓样式统一:
window.webkit.messageHandlers.JSMessageToOC.postMessage("js发给oc的一条消息:aaa");
    1. self 遵守WKScriptMessageHandler协议, 实现方法。当js给oc发送消息的时候,该协议方法会被执行:
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
       //通过message.name  message.body等获取消息。
}

2.注意循环引用问题:
self引用webView。
webView引用config。
config引用contentController。
contentController添加messageHandler为self来引用self。

打破方式: messageHandler的对象使用代理。使用proxy等

4.使用WebViewJavaScriptBridge.

1.首先需要在js中写入如下代码

function setupWebViewJavascriptBridge(callback) {
           if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
           if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
           window.WVJBCallbacks = [callback];
           var WVJBIframe = document.createElement('iframe');
           WVJBIframe.style.display = 'none';
           WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
           document.documentElement.appendChild(WVJBIframe);
           setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
       }

2.js调用oc
js给oc发消息方式如下:
1.js中执行如下方法,将数据传给oc:

WebViewJavascriptBridge.callHandler('jsCallsOC', {'argument': '18'}, function(response) {
  })

2.oc执行如下方法,获取数据.

  • data中是js传给oc的消息,
  • oc还可以通过调用responseCallback 回应js.
[self.bridge  registerHandler:@"jsCallsOC" handler:^(id data, WVJBResponseCallback responseCallback) {
        //js调用oc方法,oc执行后,可以调用responseCallback来通知js,oc执行完成了.
        NSLog(@"%@---%@",data,responseCallback);
    }];
  1. oc调用js方法,oc发消息给js
  2. oc中执行如下方法
[self.wjb callHandler:@"OCCallJSFunction" data:@"data" responseCallback:^(id responseData) {
       //oc调用js方法,  js执行完成后,会回应oc 执行后的responseData.
        NSLog(@"%@",responseData);
    }];
  1. 在js中这样写:
    oc调用js,给js发消息时, js中方法会执行.
    data是oc给js的数据.
    js执行完成后,可以调用responsecallback来回应oc.
  //所有oc调用的js方法都需要在setup方法中注册.
  setupWebViewJavascriptBridge(function(bridge) {
       // JS 被调用的方法  OCCallJSFunction 定义的标识
       bridge.registerHandler('OCCallJSFunction', function(data,   responseCallback) {
            alert('JS方法被调用:'+data);             
            responseCallback('js执行过了');
       })
   })

相关文章

网友评论

      本文标题:1.WebView与OC通讯方式

      本文链接:https://www.haomeiwen.com/subject/bnyvdqtx.html