日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

WebViewJavascriptBridge 原理分析

發(fā)布時間:2025/3/21 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WebViewJavascriptBridge 原理分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

網(wǎng)上好多都是在介紹?WebViewJavascriptBridge如何使用,這篇文章就來說說?WebViewJavascriptBridge 設(shè)計原理。

主要從兩個過程來講一下:js調(diào)用UIViewController中的代碼(Native),Native調(diào)用js


1.概述


? ?首先有兩個問題:

? ? a.Native(中的UIWebView)是否可以直接調(diào)用js method(方法)? ?可以。

? ? b.js 是否可以直接調(diào)用Native的mthod?不行。

? ?明確上述兩個問題,那么上圖就不難明白了,webpage中的js method和webview本地的method之間關(guān)系。那WebViewJavascriptBridge出現(xiàn)是否解決這個問題(這個問題就是讓js可以直接調(diào)用native的method)呢?答案是否定的?沒有本質(zhì)還是用uiwebview的代理方法進行字段攔截(判斷url的scheme),實現(xiàn)js間接調(diào)用native的method。

? ?我們來看WebViewJavascriptBridge提供的demo:

? ?

? ?主要的核心是下面兩個,接下來我們就來討論一下其設(shè)計原理。


2.js調(diào)用Native method

? 在概述中說過,js是不能直接調(diào)用native的method所以,需要借助- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType,這個方法大家不陌生,每次在重新定向URL的時候,這個方法就會被觸發(fā),通常情況,我們會在這里做一些攔截完成js和本地的間接交互什么的。那么WebViewJavascriptBridge也不另外,也是這么做。

我們先來看看在ExampleApp.html文件中點擊一個按鈕發(fā)起請求的代碼:


[html]?view plain?copy

?print?

  • var?callbackButton?=?document.getElementById('buttons').appendChild(document.createElement('button'))??

  • ????????callbackButton.innerHTML?=?'Fire?testObjcCallback'??

  • ????????callbackButton.onclick?=?function(e)?{??

  • ????????????e.preventDefault()??

  • ????????????log('JS?calling?handler?"testObjcCallback"')??

  • ????????????//1??

  • ????????????bridge.callHandler('testObjcCallback',?{'foo':?'cccccccccccc'},?function(response)?{??

  • ????????????????log('JS?got?response',?response)??

  • ????????????})??

  • ????????}??


  • 估計大家大體都能看懂,唯獨有疑問的地方是:



    [html]?view plain?copy

    ?print?

  • bridge.callHandler('testObjcCallback',?{'foo':?'cccccccccccc'},?function(response)?{??

  • ????????????????log('JS?got?response',?response)??

  • ????????????})??

  • ????????}??


  • 這段代碼先不說,上面代碼就是一個按鈕的普通單擊事件方法。我們一起想一下,如果這個按鈕需要被點擊之后調(diào)用native中的funtion函數(shù),之后需要把這個(native的)funtion函數(shù)處理結(jié)果返回給js中的方法繼續(xù)處理。這個是我們需求,帶著這個需求我們看一下這個方法,testObjcCallBack這個我們猜測一下應(yīng)該native中的方法或者一個能夠調(diào)用到方法的name/id,后面這個是個json{‘foo’:‘ccccccccccccc’},應(yīng)該是個參數(shù),那么后面這個方法一看log應(yīng)該知道,是對native返回的result進行處理的方法。拿具體是不是呢?只要找到callHandler方法就知道了。


    在文件WebViewJavascriptBridge.js.txt里面我們找找這個方法:


    [html]?view plain?copy

    ?print?

  • function?callHandler(handlerName,?data,?responseCallback)?{??

  • ????????_doSend({?handlerName:handlerName,?data:data?},?responseCallback)??

  • ????}??


  • 這里又多了一個方法叫_doSend連個參數(shù) 第1個是字典key-value定義,第二個是一個方法的指針(看看上面的方法你就知道了),那我們必須在同一個文件里面看看能不能找到這個_doSend方法:



    [html]?view plain?copy

    ?print?

  • function?_doSend(message,?responseCallback)?{??

  • ????????if?(responseCallback)?{??

  • ????????????var?callbackId?=?'cb_'+(uniqueId++)+'_'+new?Date().getTime()??

  • ????????????responseCallbacks[callbackId]?=?responseCallback??

  • ????????????message['callbackId']?=?callbackId??

  • ????????}??

  • ????????sendMessageQueue.push(message)??

  • ????????messagingIframe.src?=?CUSTOM_PROTOCOL_SCHEME?+?'://'?+?QUEUE_HAS_MESSAGE??

  • ????}??


  • 找到了。


    逐行分析一下,變量callbackId是個字符串,responseCallBacks[] 一看就知道是個字典 ,這個字典把回掉(我們猜測)的方法responseCallback給保存起來,這Key(也就是callbackId)應(yīng)該是唯一的,通過計數(shù)和時間應(yīng)該知道這個字符串應(yīng)該是唯一的,message也是一個字典,這是給message添加了一個新的key-value。干嘛呢?我也不知道,我們來看看sendMessageQueue是什么,大家一個push就知道應(yīng)該是個數(shù)組。他吧一個字典放到一個消息隊列中(數(shù)組隊列),讓后產(chǎn)生一個src(url scheme)。

    有兩個變量我們看看:


    [html]?view plain?copy

    ?print?

  • var?CUSTOM_PROTOCOL_SCHEME?=?'wvjbscheme'??

  • var?QUEUE_HAS_MESSAGE?=?'__WVJB_QUEUE_MESSAGE__'??


  • 干嘛用,肯定是給webview 的 delegate判斷用的,你感覺呢?(肯定是)


    下面是在文件:WebViewJavascriptBridge.m

    好了到了這里大家猜猜這個要干嘛?肯定是要發(fā)url讓web截取對吧?那還用問啊,肯定是啊,已經(jīng)說過了js能不能調(diào)用native的funtion函數(shù)?不能。我們來看看這個messagingIframe是:


    [html]?view plain?copy

    ?print?

  • function?_createQueueReadyIframe(doc)?{??

  • ????messagingIframe?=?doc.createElement('iframe')??

  • ????messagingIframe.style.display?=?'none'??

  • ????messagingIframe.src?=?CUSTOM_PROTOCOL_SCHEME?+?'://'?+?QUEUE_HAS_MESSAGE??

  • ????doc.documentElement.appendChild(messagingIframe)??

  • }??


  • 原來就是iframe,這個就不同給大家解釋了。好了src一產(chǎn)生就會出現(xiàn)什么,uiwebview代理回掉截獲,此時我們把目光回到UIWebview的Native下面:



    [html]?view plain?copy

    ?print?

  • -?(BOOL)webView:(UIWebView?*)webView?shouldStartLoadWithRequest:(NSURLRequest?*)request?navigationType:(UIWebViewNavigationType)navigationType?{??

  • ????if?(webView?!=?_webView)?{?return?YES;?}??

  • ????NSURL?*url?=?[request?URL];??

  • ????__strong?WVJB_WEBVIEW_DELEGATE_TYPE*?strongDelegate?=?_webViewDelegate;??

  • ??????

  • ????if?([[url?scheme]?isEqualToString:kCustomProtocolScheme])??

  • ????{??

  • ????????if?([[url?host]?isEqualToString:kQueueHasMessage])??

  • ????????{??

  • ????????????//會走這里??

  • ????????????[self?_flushMessageQueue];??

  • ????????}??

  • ????????else??

  • ????????{??

  • ????????????NSLog(@"WebViewJavascriptBridge:?WARNING:?Received?unknown?WebViewJavascriptBridge?command?%@://%@",?kCustomProtocolScheme,?[url?path]);??

  • ????????}??

  • ????????return?NO;??

  • ????}??

  • ????else?if?(strongDelegate?&&?[strongDelegate?respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)])??

  • ????{??

  • ????????return?[strongDelegate?webView:webView?shouldStartLoadWithRequest:request?navigationType:navigationType];??

  • ????}??

  • ????else??

  • ????{??

  • ????????return?YES;??

  • ????}??

  • }??


  • 一看就頭大,哈哈,是,我也頭大。看看上面的注釋說 會走這里,我們看看為什么會走那里,最外圈的if([url scheme])判斷是


    #define kCustomProtocolScheme @"wvjbscheme"

    這個定義是什么意思,我們先不做解釋,剛才我們說過js不能直接調(diào)用native的function,大家只要記住這點,接著往下走就是了。至于為什么走這里,自己看代碼(上文有提到),我們看看_flushMessageQueue:


    [html]?view plain?copy

    ?print?

  • -?(void)_flushMessageQueue?{??

  • ????NSString?*messageQueueString?=?[_webView?stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"];??

  • ????//json轉(zhuǎn)成數(shù)組??

  • ????id?messages?=?[self?_deserializeMessageJSON:messageQueueString];??

  • ????if?(![messages?isKindOfClass:[NSArray?class]])?{??

  • ????????NSLog(@"WebViewJavascriptBridge:?WARNING:?Invalid?%@?received:?%@",?[messages?class],?messages);??

  • ????????return;??

  • ????}??

  • ????for?(WVJBMessage*?message?in?messages)?{??

  • ????????if?(![message?isKindOfClass:[WVJBMessage?class]])?{??

  • ????????????NSLog(@"WebViewJavascriptBridge:?WARNING:?Invalid?%@?received:?%@",?[message?class],?message);??

  • ????????????continue;??

  • ????????}??

  • ????????[self?_log:@"RCVD"?json:message];??

  • ????????//用于js回掉??

  • ????????NSString*?responseId?=?message[@"responseId"];??

  • ????????if?(responseId)?{??

  • ????????????WVJBResponseCallback?responseCallback?=?_responseCallbacks[responseId];??

  • ????????????responseCallback(message[@"responseData"]);??

  • ????????????[_responseCallbacks?removeObjectForKey:responseId];??

  • ????????}?else?{??

  • ????????????WVJBResponseCallback?responseCallback?=?NULL;??

  • ????????????NSString*?callbackId?=?message[@"callbackId"];??

  • ????????????if?(callbackId)?{??

  • ????????????????responseCallback?=?^(id?responseData)?{??

  • ????????????????????if?(responseData?==?nil)?{??

  • ????????????????????????responseData?=?[NSNull?null];??

  • ????????????????????}??

  • ??????????????????????

  • ????????????????????WVJBMessage*?msg?=?@{?@"responseId":callbackId,?@"responseData":responseData?};??

  • ????????????????????[self?_queueMessage:msg];??

  • ????????????????};??

  • ????????????}?else?{??

  • ????????????????responseCallback?=?^(id?ignoreResponseData)?{??

  • ????????????????????//?Do?nothing??

  • ????????????????};??

  • ????????????}??

  • ??????????????

  • ????????????WVJBHandler?handler;??

  • ????????????if?(message[@"handlerName"])?{??

  • ????????????????handler?=?_messageHandlers[message[@"handlerName"]];??

  • ????????????}?else?{??

  • ????????????????handler?=?_messageHandler;??

  • ????????????}??

  • ??

  • ????????????if?(!handler)?{??

  • ????????????????[NSException?raise:@"WVJBNoHandlerException"?format:@"No?handler?for?message?from?JS:?%@",?message];??

  • ????????????}??

  • ??????????????

  • ????????????handler(message[@"data"],?responseCallback);??

  • ????????}??

  • ????}??

  • }??


  • 這下牛逼了,不忍直視啊!這么多,哈哈,多不可怕,可怕是你堅持不下去了。


    我們逐行來看:

    ?NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"];

    我們必須回去到j(luò)s文件中去,這里是webview直接調(diào)用js中的方法:


    [html]?view plain?copy

    ?print?

  • function?_fetchQueue()?{??

  • ????var?messageQueueString?=?JSON.stringify(sendMessageQueue)??

  • ????sendMessageQueue?=?[]??

  • ????return?messageQueueString??

  • }??


  • 謝天謝地這個方法代碼不多,這個消息很眼熟,SendMessageQueue,剛才我們說什么來?他是一個字典,那里面有哪些東西,我么來看看


    handlerName:handlerName,

    data:data,

    callbackId:callbackId?

    這個消息字典此時被取出來準備做什么,這里提示下我們已經(jīng)走到webview 的delegate里面了,所以拿到這些信息肯定是調(diào)用native的method對吧?肯定是的。接著往下走,接著會把json字符串轉(zhuǎn)成數(shù)組,然后進行判斷,

    [html]?view plain?copy

    ?print?

  • NSString*?responseId?=?message[@"responseId"];??

  • 有沒有responseid,你說又沒,肯定沒有啊(你不行看看上面),所以就這這里了


    [html]?view plain?copy

    ?print?

  • WVJBResponseCallback?responseCallback?=?NULL;??

  • ????????????NSString*?callbackId?=?message[@"callbackId"];??

  • ????????????if?(callbackId)?{??

  • ????????????????responseCallback?=?^(id?responseData)?{??

  • ????????????????????if?(responseData?==?nil)?{??

  • ????????????????????????responseData?=?[NSNull?null];??

  • ????????????????????}??

  • ??????????????????????

  • ????????????????????WVJBMessage*?msg?=?@{?@"responseId":callbackId,?@"responseData":responseData?};??

  • ????????????????????[self?_queueMessage:msg];??

  • ????????????????};??

  • ????????????}?else?{??

  • ????????????????responseCallback?=?^(id?ignoreResponseData)?{??

  • ????????????????????//?Do?nothing??

  • ????????????????};??

  • ????????????}??

  • ??????????????

  • ????????????WVJBHandler?handler;??

  • ????????????if?(message[@"handlerName"])?{??

  • ????????????????handler?=?_messageHandlers[message[@"handlerName"]];??

  • ????????????}?else?{??

  • ????????????????handler?=?_messageHandler;??

  • ????????????}??

  • ??

  • ????????????if?(!handler)?{??

  • ????????????????[NSException?raise:@"WVJBNoHandlerException"?format:@"No?handler?for?message?from?JS:?%@",?message];??

  • ????????????}??

  • ??????????????

  • ????????????handler(message[@"data"],?responseCallback);??

  • 這部分是重點,到底他是怎么要調(diào)用本地function的,callbackId大家熟悉吧,判斷是否為空,不為空給他指定一個block,這個不說了,block指定,此時不調(diào)用(手動調(diào)用才會執(zhí)行),這個剛才說了用來處理native的function處理的result用于把處理后的值返回給js的,接著往下去,看到handler這個方法會從message找到handlerName,這里我們看一下多了一個_messageHandlers字典,從這個字典獲取一個block(WVJBHandler是一個block),直接執(zhí)行了。那我們看看_messageHandlers是怎么被添加block的:



    [html]?view plain?copy

    ?print?

  • -?(void)registerHandler:(NSString?*)handlerName?handler:(WVJBHandler)handler?{??

  • ????_messageHandlers[handlerName]?=?[handler?copy];??

  • }??


  • 那又是誰調(diào)用了這個方法:


    找到了(在文件 ExampleAppViewController.m的viewdidload中),這里有方法testObjecCallback


    [html]?view plain?copy

    ?print?

  • [_bridge?registerHandler:@"testObjcCallback"?handler:^(id?data,?WVJBResponseCallback?responseCallback)?{??

  • ????NSLog(@"testObjcCallback?called:?%@",?data);??

  • ????responseCallback(@"Response?from?testObjcCallback");??

  • }];??


  • 有點亂了。剛才我們的思路都是倒推的,如果我們整過來,首先肯定是viewdidload初始化,初始化之后會把這個block加入到_messageHandlers中,之后因為js調(diào)用動態(tài)讀取這個block調(diào)用,在調(diào)用之前,我們又把定一個block付給回掉處理的responseCallback的block,這個block在handler中調(diào)用而調(diào)用,有點繞,自己可以多想想。


    我們接著來看看:


    [html]?view plain?copy

    ?print?

  • responseCallback?=?^(id?responseData)?{??

  • ????????????????????if?(responseData?==?nil)?{??

  • ????????????????????????responseData?=?[NSNull?null];??

  • ????????????????????}??

  • ??????????????????????

  • ????????????????????WVJBMessage*?msg?=?@{?@"responseId":callbackId,?@"responseData":responseData?};??

  • ????????????????????[self?_queueMessage:msg];??

  • ????????????????};??


  • 這個就是你繞的地方,他是后被定義的,所以一開不執(zhí)行,只有在處理數(shù)據(jù)后回調(diào)才會被調(diào)用,這里有個方法_queueMessage:



    [html]?view plain?copy

    ?print?

  • -?(void)_queueMessage:(WVJBMessage*)message?{??

  • ????if?(_startupMessageQueue)?{??

  • ????????[_startupMessageQueue?addObject:message];??

  • ????}?else?{??

  • ????????[self?_dispatchMessage:message];??

  • ????}??

  • }??


  • 這里面還有個方法:



    [html]?view plain?copy

    ?print?

  • -?(void)_dispatchMessage:(WVJBMessage*)message?{??

  • ????NSString?*messageJSON?=?[self?_serializeMessage:message];??

  • ????[self?_log:@"SEND"?json:messageJSON];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\\"?withString:@"\\\\"];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\""?withString:@"\\\""];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\'"?withString:@"\\\'"];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\n"?withString:@"\\n"];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\r"?withString:@"\\r"];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\f"?withString:@"\\f"];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\u2028"?withString:@"\\u2028"];??

  • ????messageJSON?=?[messageJSON?stringByReplacingOccurrencesOfString:@"\u2029"?withString:@"\\u2029"];??

  • ??

  • ????NSString*?javascriptCommand?=?[NSString?stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');",?messageJSON];??

  • ????if?([[NSThread?currentThread]?isMainThread])?{??

  • ????????[_webView?stringByEvaluatingJavaScriptFromString:javascriptCommand];??

  • ????}?else?{??

  • ????????__strong?WVJB_WEBVIEW_TYPE*?strongWebView?=?_webView;??

  • ????????dispatch_sync(dispatch_get_main_queue(),?^{??

  • ????????????[strongWebView?stringByEvaluatingJavaScriptFromString:javascriptCommand];??

  • ????????});??

  • ????}??

  • }??



  • 我們在回到WebViewJavascriptBridge.js.txt文件中看到


    [html]?view plain?copy

    ?print?

  • function?_handleMessageFromObjC(messageJSON)?{??

  • ????if?(receiveMessageQueue)?{??

  • ????????receiveMessageQueue.push(messageJSON)??

  • ????}?else?{//肯定走這個??為什么呢???

  • ????????_dispatchMessageFromObjC(messageJSON)??

  • ????}??

  • }??


  • 再來看看:



    [html]?view plain?copy

    ?print?

  • function?_dispatchMessageFromObjC(messageJSON)?{??

  • ????????setTimeout(function?_timeoutDispatchMessageFromObjC()?{??

  • ????????????var?message?=?JSON.parse(messageJSON)??

  • ????????????var?messageHandler??

  • ????????????var?responseCallback??

  • ??

  • ????????????if?(message.responseId)?{??

  • ????????????????responseCallback?=?responseCallbacks[message.responseId]??

  • ????????????????if?(!responseCallback)?{?return;?}??

  • ????????????????responseCallback(message.responseData)??

  • ????????????????delete?responseCallbacks[message.responseId]??

  • ????????????}?else?{??

  • ??

  • ????????????????if?(message.callbackId)?{??

  • ????????????????????var?callbackResponseId?=?message.callbackId??

  • ????????????????????responseCallback?=?function(responseData)?{??

  • ????????????????????????_doSend({?responseId:callbackResponseId,?responseData:responseData?})??

  • ????????????????????}??

  • ????????????????}??

  • ??????????????????

  • ????????????????var?handler?=?WebViewJavascriptBridge._messageHandler??

  • ????????????????if?(message.handlerName)?{??

  • ????????????????????handler?=?messageHandlers[message.handlerName]??

  • ????????????????}??

  • ??????????????????

  • ????????????????try?{??

  • ????????????????????handler(message.data,?responseCallback)??

  • ????????????????}?catch(exception)?{??

  • ????????????????????if?(typeof?console?!=?'undefined')?{??

  • ????????????????????????console.log("WebViewJavascriptBridge:?WARNING:?javascript?handler?threw.",?message,?exception)??

  • ????????????????????}??

  • ????????????????}??

  • ??

  • ????????????}??

  • ????????})??

  • ????}??


  • 大家還記得我們返回的對象是:

    [html]?view plain?copy

    ?print?

  • @{?@"responseId":callbackId,?@"responseData":responseData?}??


  • 所以這里messageHandlers剛才也說過了用來存方法的,callbackId被換了個名字叫responseId意思一樣,只要值沒變就行,所以就會執(zhí)行:


    [html]?view plain?copy

    ?print?

  • bridge.callHandler('testObjcCallback',?{'foo':?'cccccccccccc'},?function(response)?{??

  • ????????????????log('JS?got?response',?response)??

  • ????????????})??


  • 中的方法,好了,完了。



    總結(jié)一下:js這邊 先把方法名字、參數(shù)、處理方法保存成一個字典在轉(zhuǎn)成json字符串,在通過UIWebview調(diào)用js中某個方法把這個json字符串傳到Native中去(不是通過url傳的,這樣太low了),同時把這個處理的方法以key-value形式放到一個js的字典中。

    ? ? ? ? ? ? ? ? ?UIWebView在收到這個json之后,進行數(shù)據(jù)處理、還有js的回掉的處理方法(就是那個callbackId)處理完成后也會拼成一個key-value字典通過調(diào)用js傳回去(可以直接調(diào)用js)。

    ? ? ? ? ? ? ? ? ?js在接到這個json后,根據(jù)responseId讀取responseCallbacks中處理方法進行處理Native code返回的數(shù)據(jù)。

    3.Native調(diào)用js method

    ? ? 過程不是直接調(diào)用js,也是通過js調(diào)用Native過程一樣的處理方式。

    ? ? 大體來看一下,先看一個按鈕的單擊事件:

    ? ??

    [html]?view plain?copy

    ?print?

  • -?(void)callHandler:(id)sender?{??

  • ????id?data?=?@{?@"greetingFromObjC":?@"Hi?there,?JS!"?};??

  • ????[_bridge?callHandler:@"testJavascriptHandler"?data:data?responseCallback:^(id?response)?{??

  • ????????NSLog(@"testJavascriptHandler?responded:?%@",?response);??

  • ????}];??

  • }??


  • 看看callHandler:


    [html]?view plain?copy

    ?print?

  • -?(void)callHandler:(NSString?*)handlerName?data:(id)data?responseCallback:(WVJBResponseCallback)responseCallback?{??

  • ????[self?_sendData:data?responseCallback:responseCallback?handlerName:handlerName];??

  • }??


  • 看看_sendData:



    [html]?view plain?copy

    ?print?

  • -?(void)_sendData:(id)data?responseCallback:(WVJBResponseCallback)responseCallback?handlerName:(NSString*)handlerName?{??

  • ????NSMutableDictionary*?message?=?[NSMutableDictionary?dictionary];??

  • ??????

  • ????if?(data)?{??

  • ????????message[@"data"]?=?data;??

  • ????}??

  • ??????

  • ????if?(responseCallback)?{??

  • ????????NSString*?callbackId?=?[NSString?stringWithFormat:@"objc_cb_%ld",?++_uniqueId];??

  • ????????_responseCallbacks[callbackId]?=?[responseCallback?copy];??

  • ????????message[@"callbackId"]?=?callbackId;??

  • ????}??

  • ??????

  • ????if?(handlerName)?{??

  • ????????message[@"handlerName"]?=?handlerName;??

  • ????}??

  • ????[self?_queueMessage:message];??

  • }??


  • 到_queueMessage:之后流程就和上面一樣了,這里面native也有個:



    [html]?view plain?copy

    ?print?

  • NSString*?responseId?=?message[@"responseId"];??

  • ???????if?(responseId)?{??

  • ???????????WVJBResponseCallback?responseCallback?=?_responseCallbacks[responseId];??

  • ???????????responseCallback(message[@"responseData"]);??

  • ???????????[_responseCallbacks?removeObjectForKey:responseId];??

  • ???????}??


  • 這個和js中的處理思想是一樣的。



    總結(jié):native將方法名、參數(shù)、回到的id放到一個對象中傳給js。

    ? ? ? ? ? ?js根據(jù)方法名字調(diào)用相應(yīng)方法,之后將返回數(shù)據(jù)和responseId拼裝,最后通過src 重定向到UIWebview 的delegate。

    ? ? ? ? ? ?native得到數(shù)據(jù)后根據(jù)responseId調(diào)用事先裝入_responseCallbacks的block,動態(tài)讀取調(diào)用,從而完成交互。



















    本文轉(zhuǎn)自ljianbing51CTO博客,原文鏈接:?http://blog.51cto.com/ljianbing/1857876,如需轉(zhuǎn)載請自行聯(lián)系原作者

    總結(jié)

    以上是生活随笔為你收集整理的WebViewJavascriptBridge 原理分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。