前提條件都是須要bridge在OC實例化,而後兩者的互調才能夠進行下去javascript
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
實例化的原理是:JSBridge裏面有UIWebview和JSBridgeBase的實例,而後分別成爲兩者的代理,負責協調雙方的工做html
由OC註冊,JS主動觸發(調用callhandler方法)java
[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback)
,該回調函數包括一個註冊事件和一個回調方法,JSB中的base實例會把該註冊事件放進到base的一個消息池子(負責接受多個OC註冊事件)中,方便後續處理web
至關於JS的註冊綁定方法--->當UIWebview把該網頁加載出來的時候,在該html文件中會經過JS的iframe元素執行JS和OC端的綁定。函數
該方法是因爲webview的delegate設置爲了JSB,因此會在JSB中觸發其代理方法:shouldStartLoadWithRequest,而後在該方法中進行以下操做:fetch
根據url(此時的url是由上述的iframe元素帶進來的,相似:wvjbscheme://BRIDGE_LOADED ) ,來決定此時是走registerHandler 仍是 callHandler方法,此時是register方法,那麼則執行JSBridgeBase的injectJavascriptFile方法(正如函數名同樣,此時執行在工程裏面放置的JS文件(在咱們的工程裏面因爲要兼容JSBridge的歷史版本,因此這裏是在webViewDidFinishLoad裏面直接調用injectJavascriptFile方法)),這個文件的主要做用就是向OC發消息來定義一些常量,註冊一些實例,定義一些回調方法,方便在OC的邏輯中進行處理和跟蹤,文件執行完畢後,接下來就會查找在base中時候有OC要發送給JS的回調信息,沒有則執行結束(這裏顯然沒有)lua
點擊JS上的button會觸發callHandler,會觸發代理shouldStartLoadWithRequest:
此時因爲經由上述的JS文件執行的時候會執行一個叫作window.WebViewJavascriptBridge的註冊url
window.WebViewJavascriptBridge = { registerHandler: registerHandler, callHandler: callHandler, disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout, _fetchQueue: _fetchQueue, _handleMessageFromObjC: _handleMessageFromObjC };
因爲js主動觸發了callHandler,url因此變成了
wvjbscheme://WVJB_QUEUE_MESSAGE ,因此此時會走一個執行js函數的方法(猜想是經過上述js文件的做用從而可以解析出JS傳遞過來的信息)來從網頁上得到網頁的傳遞過來的信息!spa
{ "callbackId" : "cb_2_1468844907930", "handlerName" : "testObjcCallback", "data" : { "foo" : "bar" } }
而後進入base的flushMessageQueue:函數,在裏面經過解析該dict,從而得到註冊事件名handlerName,而後得到該事件的回調,並調用那個事件的回調block線程
handler(message[@"data"], responseCallback);
至此,整個JS回調OC過程完成,達到了JS給OC發送數據的目的,同時若是OC想要給JS發送消息,只需把信息放進responseCallback就會回調給JS(方法就是第二部分的內容),以達到互相通訊的目的
由js註冊,OC主動觸發(調用callhandler方法)
至關於JS的註冊方法--->當UIWebview把該網頁加載出來的時候,在該html文件中會經過JS的iframe元素執行JS和OC端的綁定。
該方法的因爲webview的delegate設置爲了JSb,因此會在JSB中觸發其代理方法:shouldStartLoadWithRequest,而後在該方法中進行以下操做:
根據url(此時的url是由上述的iframe元素帶進來的,相似:wvjbscheme://BRIDGE_LOADED ) ,來決定此時是走registerHandler 仍是 callHandler方法,此時是register方法,那麼則執行JSBridgeBase的injectJavascriptFile方法(正如函數名同樣,此時執行在工程裏面放置的JS文件),這個文件的主要做用就是向OC發消息來定義一些常量,註冊一些實例,定義一些回調方法,方便在OC的邏輯中進行處理和跟蹤,
其中會執行一個叫作window.WebViewJavascriptBridge的註冊
window.WebViewJavascriptBridge = { registerHandler: registerHandler, callHandler: callHandler, disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout, _fetchQueue: _fetchQueue, _handleMessageFromObjC: _handleMessageFromObjC };
因爲js函數中一進來便主動觸發了registerHandler,因此url變成了
wvjbscheme://WVJB_QUEUE_MESSAGE
文件執行完畢後,會在JSB中執行
else if ([_base isQueueMessageURL:url]) { NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; [_base flushMessageQueue:messageQueueString]; }
剛好此時url 知足狀況,則進入消息分發流程,可是因爲此時messageQueueString什麼也沒有,因此直接跳出
點擊OC的button,觸發OC函數
[_bridge callHandler:@"testJavascriptHandler" data:@{@"name": @"wayne"} responseCallback:^(id responseData)
調用Base的
- (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName
使用dictionary進行消息拼接,形如:
{ callbackId = "objc_cb_1";//定義OC的回調id data = { name = wayne; };//OC傳遞給JS的數據 handlerName = testJavascriptHandler;//爲了區分是哪個註冊事件,以便後續的消息分發 }
封裝完成事後,會調用[self _dispatchMessage:message]來進行消息分發,消息分發是在主線程裏面執行的,消息的內容通過再次封裝事後形似:
WebViewJavascriptBridge._handleMessageFromObjC('{\"callbackId\":\"objc_cb_1\",\"data\":{\"name\":\"wayne\"},\"handlerName\":\"testJavascriptHandler\"}');
WebViewJavascriptBridge._handleMessageFromObjC-->查看JS文件可知,這個文件是給JS使用的,會執行_handleMessageFromObjC的方法把消息分發給JS中的registerHandler中的方法體,OC回調過程結束!!
可是此時在執行JS中的代碼的時候發現有回調block,則會執行改block
而後會再次執行UIWebview的代理方法:shouldStartLoadWithRequest函數,此時url已是
wvjbscheme://WVJB_QUEUE_MESSAGE
文件執行完畢後,會在JSB中執行
else if ([_base isQueueMessageURL:url]) { NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; [_base flushMessageQueue:messageQueueString]; }
messageQueueString由第一部分知識可知:是JS傳遞過來的數據:
[{ "handlerName":"testJavascriptHandler", "responseId":"objc_cb_1", "responseData": {"Javascript Says":"Right back atcha!==>test"} }]
執行flushMessageQueue函數:並在裏面執行block函數體,得到JS傳遞過來的數據
至此,互相傳遞數據過程完畢!