一、bridge 初始化
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
這里并沒有注冊 js 的 bridge饲漾。而是在 js 第一次調(diào)用 native 的時候证鸥,才去執(zhí)行的 bridge 中的 js 方法镜硕。去注冊 js 端的 bridge。
二血淌、native 注冊 methods
native 調(diào)用 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 調(diào)用 native 方法的時候眼五,window.WebViewJavascriptBridge
是沒有值的诵姜,所以下面會調(diào)用一個 https://__bridge_loaded__
的鏈接鞋囊,native 端 bridge 接收到這個鏈接后溜腐,才去執(zhí)行 注入的 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]) {// 判斷是 執(zhí)行方法
[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);
}
}