WebViewJavascriptBridge浅析

作者 新城 日期 2018-03-26
WebViewJavascriptBridge浅析

javascript和安卓iOS之间约定的相互调用彼此接口的桥梁 参考

WebViewJavascriptBridge

原理

OC环境和Javascript环境各自保存一个相互调用的bridge对象,每一个调用之间都有id和callbackid来找到两个环境对应的处理。

核心类

  • WebViewJavascriptBridge_JS:Javascript环境的Bridge初始化和处理。负责接收OC发给Javascript的消息,并且把Javascript环境的消息发送给OC。

  • WKWebViewJavascriptBridge / WebViewJavascriptBridge : 主要负责OC环境的消息处理 并且吧OC 环境的消息发送给javascript环境

  • WebViewJavascriptBridgeBase:主要实现了OC环境的Bridge初始化和处理。

1.1 原生环境初始化
1.2 原生环境注册方法

1.3 javascript 初始化和注册方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function setWebViewJavascriptBridge(callback) {
// 第一次调用这个方法的时候 为false
if (window.WebViewJavascriptBridge) {
return callback(WebJavascriptBridge)
}

// 第一次调用的时候 为false
if(window.WVJBCallback) {
return window.WVJBCallback.push(callback)
}

// 将callback赋值给对象
window.WVJBCallback = [callback]

// 创建iframe 追加在body之后 初始化之后 在将其移除

var WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = none
WVJBIframe.src = 'https://__bridge_loaded__'
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}

setupWebViewJavascriptBridge(function(bridge) {
// 把WEB中注册的方法注册到bridge里面
bridge.registerHandler('testJavascriptHandler', function(data,responseCallback){

// OC 传递过来的数据
log('ocjC call testJavascript with', data);

// js返回数据
var responseData = {'Javascript Says':'Right back atcha'}
responseCallback(responseData)

})
})

1.4

1.5 javascript发送消息给OC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// testObjcHandler  类似于接口 {'foo' : 'bar'} 类似于数据  response 类似于响应消息
bridge.callHandler('testObjcHandler', {'foo': 'bar'}, function(response) {
log('JS got response', response)-->
})


//web端调用一个OC注册的消息
function callHandler(handlerName, data, responseCallback) {
if (arguments.length == 2 && typeof data == 'function') {
responseCallback = data;
data = null;
}
_doSend({ handlerName: handlerName, data: data }, responseCallback);
}


//JS调用OC方法,执行具体的发送操作
function _doSend(message, responseCallback) {
if (responseCallback) {
var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime();
//存储消息的回调ID
responseCallbacks[callbackId] = responseCallback;
//把消息对应的回调ID和消息一起发送,以供消息返回以后使用
message['callbackId'] = callbackId;
}
//把消息放入消息列表
sendMessageQueue.push(message);
//下面这句话会发起JS对OC的调用,让webview执行跳转操作,从而可以在
//webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
//中拦截到JS发给OC的消息
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
}

总结

  1. 分别在OC环境和Javascript环境都保存bridge对象, 在bridge对象中都保存的resquestID 和对应的callbackID函数 以及对应ID具体的实现方法
  2. OC通过Javascript环境的window.WebViewJavascriptBridge对象来调用JS方法
  3. javascript 通过改变iframe的Src来唤起web view的代理方法从而实现把javascript消息发送给OC的功能

// webstorm 注册码见注释