# WebViewJavascriptBridge

把 OC 的方法注册到桥梁中,让 JS 去调用。 把 JS 的方法注册在桥梁中,让 OC 去调用。

# WebViewJavaScriptBridge 使用的基本步骤

1.首先在项目中导入 WebViewJavaScriptBridge 框架。

pod ‘WebViewJavascriptBridge’
1

2.导入头文件 #import <WebViewJavascriptBridge.h>。 3.建立 WebViewJavaScriptBridge 和 WebView 之间的关系。

_jsBridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
1

4.在 HTML 文件中,复制粘贴这两段 JS 函数。

function setupWebViewJavascriptBridge(callback) {
  if (window.WebViewJavascriptBridge) {
    return callback(WebViewJavascriptBridge);
  }
  if (window.WVJBCallbacks) {
    return window.WVJBCallbacks.push(callback);
  }
  window.WVJBCallbacks = [callback]; // 创建一个 WVJBCallbacks 全局属性数组,并将 callback 插入到数组中。
  var WVJBIframe = document.createElement("iframe"); // 创建一个 iframe 元素
  WVJBIframe.style.display = "none"; // 不显示
  WVJBIframe.src = "wvjbscheme://__BRIDGE_LOADED__"; // 设置 iframe 的 src 属性
  document.documentElement.appendChild(WVJBIframe); // 把 iframe 添加到当前文导航上。
  setTimeout(function() {
    document.documentElement.removeChild(WVJBIframe);
  }, 0);
}

// 这里主要是注册 OC 将要调用的 JS 方法。
setupWebViewJavascriptBridge(function(bridge) {});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

到此为止,基本的准备工作就做完了。现在需要往桥梁中注入 OC 方法 和 JS 函数了。

# 往桥梁中注入 OC 方法 和 JS 函数

往桥梁中注入 OC 方法。

[_jsBridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"dataFrom JS : %@",data[@"data"]);

        responseCallback(@"扫描结果 : www.baidu.com");
    }];

1
2
3
4
5
6

这段代码的意思: 1.scanClick 是 OC block 的一个别名。 2.block 本身,是 JS 通过某种方式调用到 scanClick 的时候,执行的代码块。 3.data ,由于 OC 这端由 JS 调用,所以 data 是 JS 端传递过来的数据。 4.responseCallback OC 端的 block 执行完毕之后,往 JS 端传递的数据。

往桥梁中注入 JS 函数.

OC 方法,在 OC 中注入。JS 的方法所以必然就需要在 JS 中注入的。(好像是废话) 在 JS 的方法如何注入到桥梁呢?

之前,在准备工作的时候,有两段 JS 代码。 需要在第二段 JS 代码中,注入 JS 的函数。

// 这里主要是注册 OC 将要调用的 JS 方法。
setupWebViewJavascriptBridge(function(bridge) {
  // 声明 OC 需要调用的 JS 方法。
  bridge.registerHanlder("testJavaScriptFunction", function(
    data,
    responseCallback,
  ) {
    // data 是 OC 传递过来的数据.
    // responseCallback 是 JS 调用完毕之后传递给 OC 的数据
    alert("JS 被 OC 调用了.");
    responseCallback({ data: "js 的数据", from: "JS" });
  });
});
1
2
3
4
5
6
7
8
9
10
11
12
13

这段代码的意思: 1.testJavaScriptFunction 是注入到桥梁中 JS 函数的别名。以供 OC 端调用。 2.回调函数的 data。 既然 JS 函数由 OC 调用,所以 data 是 OC 端传递过来的数据。 3.responseCallback 。 JS 调用在被 OC 调用完毕之后,向 OC 端传递的数据。

基本就是: OC 端注册 OC 的方法,OC 端调用 JS 的函数。 JS 端注册 JS 的函数,JS 端调用 OC 的方法。

# WebViewJavascriptBridge 实现原理

从setupWebViewJavascriptBridge函数来看感觉 WebViewJavascriptBridge 是通过 URL Scheme 的方式来实现的。

但是在 JSBridge 中我们提到,这种方式是有意缺点的。

TIP

🤔 那么 WebViewJavascriptBridge 是怎么实现的呢?

# 通信流程

# 代码实现方式

# 总结

  • 分别在 OC 环境和 javascript 环境都保存一个 bridge 对象,里面维持着 requestId,callbackId,以及每个 id 对应的具体实现。
  • OC 通过 javascript 环境的 window.WebViewJavascriptBridge 对象来找到具体的方法,然后执行。
  • javascript 通过改变 iframe 的 src 来出发 webview 的代理方法 webView:(WKWebView _)webView decidePolicyForNavigationAction:(WKNavigationAction _)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler 从而实现把 javascript 消息发送给 OC 这个功能。

TIP

简单来说 URL Scheme 拦截有参数长度限制的缺点,代码注入有不安全的缺点 WebViewJavascriptBridge 两者结合 通过 URL Scheme 拦截获取到一个 id,然后去 h5 的全局对象上 根据 id 拿到实际的参数,之后根据参数处理好业务之后,再执行和 id 相关的一个回调函数,把结果传给这个函数