對于JS與OC交互的再次理解(強烈呼吁摒棄百度搜索,推薦google、必應(yīng))

文字較多,耐心讀一下,肯定有所收益!

*開發(fā)中經(jīng)常使用WebViewJavascripBridge進(jìn)行H5與原生的交互,也知道OC用代理攔截H5的url做出一些操作,OC可以注入JS代碼改變H5的樣式什么的,但一直困惑的我的是:

  • 他們是怎么把我OC端的一個NSDictionary、NSArray、NSString的數(shù)據(jù)發(fā)給H5端的,又怎么把H5端的數(shù)據(jù)發(fā)給我的呢 ????????????
  • 最后明白了【數(shù)據(jù)通道】 :
  • webview注入js代碼的API:evaluateJavaScript: completionHandler:^(id _Nullable result, NSError * _Nullable error){ }

兩端 數(shù)據(jù)傳遞 通道

 //1. OC端需要注入【可執(zhí)行的JS代碼】的字符串: @"fuction('data')",OC端的可以將數(shù)據(jù)以JS方法fuction的參數(shù) data 傳入,在fuction中將數(shù)據(jù)data取出以供HTML端使用。
 [webView evaluateJavaScript:@"fuction('data')" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
    //2. result 是執(zhí)行完JS代碼后返回的結(jié)果,HTML端的數(shù)據(jù)可以通過result返回到OC端以供使用,即執(zhí)行fuction方法后,return一個數(shù)據(jù)交給OC端。
    //3. error 是執(zhí)行完JS代碼時遇到的error,可忽略。
  }];

兩端的數(shù)據(jù)傳遞具體過程

總結(jié)性的講:

  1. OC端發(fā)數(shù)據(jù)是組裝好數(shù)據(jù)直接發(fā);
  2. HTML端發(fā)數(shù)據(jù)是組裝好數(shù)據(jù),通知OC端自己過來取數(shù)據(jù)。
  • OC端發(fā)送數(shù)據(jù):
    1. 準(zhǔn)備數(shù)據(jù):創(chuàng)建一個字典,以key-Value的形式組裝成一個data,然后將data序列化成一個轉(zhuǎn)義后的json字符串;
    2. 利用注入JS代碼通道:[webView evaluateJavaScript:@"sendData('data')" completionHandler:^(id _Nullable result, NSError * _Nullable error) { }];
    直接將data送入JS代碼中,并在sendData方法中將data取出,以供HTML頁面使用處理邏輯什么的。
  • JS端發(fā)送數(shù)據(jù):
    1. 準(zhǔn)備數(shù)據(jù):js創(chuàng)建一個對象,以key-value的形式組裝一個data,然后將data序列化成json字符串;
    2. 利用一個<i>標(biāo)簽,重設(shè)一下改標(biāo)簽的src(該src是兩端約定好的),發(fā)起一個請求;
    3. OC端通過WebView的代理方法攔截到了url,判斷一下url是否是之前約定好的HTML發(fā)送數(shù)據(jù)的url,如果是則組織一段JS代碼字符串: @"getData()";
    4. OC端利用注入JS代碼通道:[webView evaluateJavaScript:@"getData()" completionHandler:^(id _Nullable result, NSError * _Nullable error) { // result :HTML端返回的數(shù)據(jù) }];
    JS代碼中執(zhí)行g(shù)etData()方法,在該方法中JS將組裝好的data,return出來。
    5. 然后 OC 端再從Block中獲取到HTML端發(fā)送的數(shù)據(jù)data,從data中取出數(shù)據(jù)處理相關(guān)邏輯。
知道了JS與OC之間的數(shù)據(jù)傳輸通道,以及傳輸?shù)木唧w過程后,我們再看這個框架。發(fā)現(xiàn)兩端創(chuàng)建的bridge,其實就是在為這個數(shù)據(jù)傳輸通道做輔助工作,比如js端定義了兩個方法:function _fetchQueue()、function _handleMessageFromObjC( data ),前一個方法是OC獲取JS端數(shù)據(jù)時注入js代碼字符串執(zhí)行該方法,該方法將js端的數(shù)據(jù)return出來;后一個方法是OC將數(shù)據(jù)傳送JS端時,將OC端數(shù)據(jù)作為該方法的參數(shù),注入js代碼字符串執(zhí)行該方法,完成了將數(shù)據(jù)傳給JS操作。因此可見,bridge就是為這條數(shù)據(jù)通道做輔助工作的。
就是因為沒搞明白這條結(jié)論,才導(dǎo)致網(wǎng)絡(luò)上介紹WebViewJavascripBridge框架的文章,將重點放在bridge上講,講bridge是如何如何執(zhí)行這個方法,那個方法,把代碼流程講了一遍,看似講明白了,但真的是隔靴搔癢,未講到核心點。一開始我也是這樣,慚愧!
  • 有了以上的認(rèn)識之后,我們再看bridge。我們都知道兩端都一個bridge,剛才也說了bridge就是為數(shù)據(jù)通道服務(wù)的,那么bridge都能幫數(shù)據(jù)通道做什么呢?有通過哪些東西輔助呢?
    只要介紹bridge提供的輔助工具就能全部理解了:
    一個屬性、 兩張表、 四個方法。

*一個屬性:sendMessageQueue,是一個數(shù)組類型,用于存儲該端組裝的Message,即Message的集合。這里的Message就是一個一個的數(shù)據(jù)包,是key-Vlaue的對象。為什么是用數(shù)組呢?個人認(rèn)為保證數(shù)據(jù)傳遞順序。

*兩張表:方法表:保存的是該端對外注冊的方法以供一端發(fā)送消息調(diào)用,以key-value的形式保存,比如:“買蘋果”:{ 買蘋果的具體操作函數(shù) }。
回調(diào)表:保存的是發(fā)送消息讓另一端執(zhí)行后的回調(diào),也是以key-value的形式保存,其key是按照一定規(guī)則創(chuàng)建保證其唯一性,比如:"買手表的回調(diào)":{把表買回來之后的操作函數(shù)}

  • 四個方法:1. 注冊方法:兩端約定一個key,將key對應(yīng)執(zhí)行的方法保存到表。
    2 . 發(fā)消息方法:使用約定好的key,在帶上數(shù)據(jù)data,發(fā)送消息讓另一端執(zhí)行相關(guān)操作,如果需要執(zhí)行完成后給出回調(diào),則在發(fā)送消息時也把回調(diào)處理的block帶上,那這個block會存在回調(diào)表。
    3 . 組裝數(shù)據(jù)方法:將發(fā)送消息方法中提供的key、data、block的key組裝成功一個Message,并轉(zhuǎn)成json字符串,以供發(fā)送給另一端使用。
    4 . 解析數(shù)據(jù)方法:將另一端發(fā)送到數(shù)據(jù),從json字符串轉(zhuǎn)成一個key-value對象,根據(jù)key,從方法表中找到方法,并將data最為該方法的參數(shù),然后執(zhí)行該方法,執(zhí)行完成后,如果從message中能獲取到block的key,則將block的key和執(zhí)行后的結(jié)果數(shù)據(jù),在發(fā)送消息給另一端,另一端獲取到消息后,從回調(diào)表中根據(jù)key找到block,然后將回到來的數(shù)據(jù)作為block參數(shù),執(zhí)行回調(diào)block。

例子:OC端讓H5端買手表

1. H5端在事件表注冊事件:“買手表” :{...}
2. OC端在回調(diào)表中保存買表的回調(diào):"callbackID" : {買表后的回調(diào)}
3. OC端創(chuàng)建了一個Message:{handleName:"買手表", data : "1000元", responseCallback : "callbackID"},保存在sendMessageQueue中
4. OC端通過【組裝數(shù)據(jù)方法】將message從sendMessageQueue中取出轉(zhuǎn)成了一個json字符串,并將該數(shù)據(jù)以參數(shù)的形式放入拼接的JS代碼字符串中,這段JS代碼就是執(zhí)行JS端【解析數(shù)據(jù)方法】
5. OC端通過數(shù)據(jù)通道將數(shù)據(jù)傳入JS端
6. JS端執(zhí)行【解析數(shù)據(jù)方法】,在方法中將參數(shù),從json字符串轉(zhuǎn)成key-value對象,得到handleNmae、data、callBackID。首先根據(jù)handleNmae從注冊表中找到買表的函數(shù),然后將data中的【1000元】作為參數(shù)執(zhí)行買手表的{...買手表去嘍...}
7. JS端買完手表后,需要將手表返回給OC端,這時JS端將callbackID和表組成了一個Message:{responsID:"callbackID" , data : 表 },保存到sendMessage中
8. JS端通過一個i標(biāo)簽,改變src發(fā)起一個請求,通知OC端過來拿數(shù)據(jù)
9. OC端攔截到url,得知要他去取數(shù)據(jù),則組織了一段JS代碼,通過數(shù)據(jù)通道將數(shù)據(jù)拿回來,即調(diào)用JS端的【組裝數(shù)據(jù)方法】將從sendMessageQueue中拿到Message返回到OC端
10. OC端拿到數(shù)據(jù)后,獲取callbackID,并根據(jù)它從回調(diào)表中找到回調(diào)的block,取出data:表,將表作為block的參數(shù)執(zhí)行block。這時OC已經(jīng)拿到了他的表了,到此結(jié)束。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容