一、bridge 初始化
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
这里并没有注册 js 的 bridge。而是在 js 第一次调用 native 的时候,才去执行的 bridge 中的 js 方法。去注册 js 端的 bridge。
二、native 注册 methods
native 调用 registerHandler
方法,并没有真的注入方法到 js context 里面,而是存储到了_base.messageHandlers
这个Dictionary 中。
[self.bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"ObjC Echo called with: %@", data);
responseCallback(data);
}];
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
_base.messageHandlers[handlerName] = [handler copy];
}
三、注册 js 端的 bridge
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 = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
在第一个 js 调用 native 方法的时候,window.WebViewJavascriptBridge
是没有值的,所以下面会调用一个 https://__bridge_loaded__
的链接,native 端 bridge 接收到这个链接后,才去执行 注入的 js 端 bridge。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if (webView != _webView) { return; }
NSURL *url = navigationAction.request.URL;
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
if ([_base isWebViewJavascriptBridgeURL:url]) {
if ([_base isBridgeLoadedURL:url]) {// 判断是 load bridge的 url
[_base injectJavascriptFile];
} else if ([_base isQueueMessageURL:url]) {// 判断是 执行方法
[self WKFlushMessageQueue];
} else {
[_base logUnkownMessage:url];
}
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) {
[_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];
} else {
decisionHandler(WKNavigationActionPolicyAllow);
}
}