混合開發Js bridge新秀-DSBridge iOS篇

來源:互聯網
上載者:User

標籤:objc   dna   非同步呼叫   手動   nullable   adr   handler   setup   過程   

這個DSBridge 和我之前開發做的混合開發 用的方式 很相似,所以覺得很是不錯,推薦給你大家.

 

DSBridge-IOS:https://github.com/wendux/DSBridge-IOS

DSBridge-Android:https://github.com/wendux/DSBridge-Android

與WebViewJavascriptBridge的對比請移步 DSBridge VS WebViewJavascriptBridge。

原文連結:http://www.jianshu.com/p/3946605109ed

 

五分鐘瞭解DSBridge

Web端

假設Native端實現了兩個api: testSyn、testAsyn。參數以json傳遞, testSyn為同步api,執行結束後會直接返回結果,而testAsyn為一個非同步api(可能會執行耗時操作),執行結束後,結果非同步返回。下面我們看看web端如何調用。

Javascript調用Native

 

var bridge = getJsBridge();var str=bridge.call("testSyn", {msg: "testSyn"});bridge.call("testAsyn", {msg: "testAsyn"}, function (v) {  alert(v);})

 

簡單到不用解釋!太優雅了。如果你體會不來,你也許應該去看看當今(馬上將會成為曆史)人氣最高的WebViewJavascriptBridge ,相信你看完之後會回來的。

 

getJsBridge

功能:擷取javascript bridge對象。

等等,貌似和我之前使用的其他庫不一樣,難道不需要像WebViewJavascriptBridge那樣先聲明一個setupWebViewJavascriptBridge的回調?你有這種疑問很正常,先給出答案:不需要,DSBridge不需要前端任何安裝代碼,隨用隨取。DSBridge的設計原則就是:讓三端使用方式都是最簡單的! DSBridge擷取bridge時,不依賴任何回調,也無需等待頁面載入結束(如果您體會不到,可以對比WebViewJavascriptBridge 前端調用方式)。ps: 這在ios>=8,android>sdk19上測試都沒問題, DSBridge也對ios7.0-8.0,android sdk16-19之間的版本做了相容,但是考慮到測試覆蓋面的問題,建議所有代碼都在dom ready之後執行。

bridge.call(method,[args,callback])

功能:調用Native api

method: api函數名

args:參數,類型:json, 選擇性參數

callback(String returnValue):僅調用非同步api時需要.

同步調用

如果你是一名經驗豐富的開發人員,想必看到第二行時已然眼睛一亮,想想node最被詬病的是什麼,目前跨平台的jsbridge中沒有一個能支援同步,所有需要擷取值的調用都必須傳一個回調,如果調用邏輯比較複雜,必將會出現“callback hell”。然而,DSBridge徹底改變了這一點。支援同步是DSBridge的最大亮點之一。

非同步呼叫

對於一些比較耗時的api, DSBridge提供了非同步支援,正如上例第三行代碼所示,此時你需要傳一個回調(如果沒有參數,回調可作為第二個參數),當api完成時回調將會被調用,結果以字串的形式傳遞。

供Native調用Javascript api

假設網頁中要提供一個函數test供native調用,只要將函式宣告為全域函數即可:

function test(arg1,arg2){  return arg1+arg2;}

如果你的代碼是在一個閉包中,將函數掛在window上即可:

 

window.test=function(arg1,arg2){      return arg1+arg2;}

 

這樣一來端上即可調用

 

iOS端實現Api

API的實現非常簡單,只需要將您要暴漏給js的api放在一個類中,然後統一註冊即可。

//JsApiTest.m@implementation JsApiTest- (NSString *) testSyn:(NSDictionary *) args{    return [(NSString *)[args valueForKey:@"msg"] stringByAppendingString:@"[ syn call]"];}- (void) testAsyn:(NSDictionary *) args :(void (^)(NSString * _Nullable result))handler{    handler([(NSString *)[args valueForKey:@"msg"] stringByAppendingString:@"[ asyn call]"]);}@end

testSyn為同步api, js在調用同步api時會等待native返回,返回後js繼續往下執行。

testAsyn為非同步api, 非同步作業時調用handler.complete通知js,此時js中設定的回調將會被調用。

為了在ios和android平台下相容,對IOS端Native API介面約定如下:

  1. 傳回值類型存在時為NSString、不存在時為void。
  2. 參數以JSON傳遞; DSBridge會將js參數自動轉化為NSDictionary 

註:JsApiTest.m中實現的方法可以不在JsApiTest.h中聲明

註冊Api
DWebview * webview=[[DWebview alloc] initWithFrame:bounds];jsApi=[[JsApiTest alloc] init];webview.JavascriptInterfaceObject=jsApi;

DWebview是sdk中提供的,您也可以使用其它兩個,這將在後文介紹。

可見對於Native來說,通過一個單獨的類實現js api, 然後直接註冊(而不需要像其它一些js bridge每個api都要單獨註冊),這樣不僅非常簡單,而且結構清晰。

 

調用Javascript

DWebView提供了兩個api用於調用js

 

//調用js api(函數)-(void)callHandler:(NSString *)methodName arguments:(NSArray * _Nullable)args                    completionHandler:(void (^)(NSString * _Nullable))completionHandler;//執行任意js代碼- (void)evaluateJavaScript:(NSString *)javaScriptString                   completionHandler:(void (^ _Nullable)(NSString * _Nullable))completionHandler;

 

callHandler中,methodName 為js函數名,args為參數數組,可以接受數字、字串等。

兩個函數中completionHandler為完成回調,用於擷取js執行的結果。

調用時機

DWebview只有在javascript context初始化成功後才能正確執行js代碼,而javascript context初始化完成的時機一般都比整個頁面載入完畢要早,隨然DSBridge能捕獲到javascript context初始化完成的時機,但是一些js api可能聲明在頁面尾部,甚至單獨的js檔案中,如果在javascript context剛初始化完成就調用js api, 此時js api 可能還沒有載入,所以會失敗,為此專門提供了一個api設定一個回調,它會在頁面載入結束後調用,為了和didpagefinished區分,我們取名如下:

- (void)setJavascriptContextInitedListener:(void(^_Nullable)(void))callback;

若是端上主動調用js,請在此回調中進行 。樣本如下:

__block DWebview * _webview=webview;[webview setJavascriptContextInitedListener:^(){  [_webview callHandler:@"test"  arguments:[[NSArray alloc] initWithObjects:@1,@"hello", nil]  completionHandler:^(NSString *  value){      NSLog(@"%@",value);  }];}];

完整的樣本請查看demo工程。

關於DWebview

SDK中有三個webview:

DWKwebview:繼承自WKWebView,內部已經實現js prompt、alert、confirm函數對應的對話方塊。

DUIwebview:繼承自UIWebView

DWebview:自訂view, 內部在ios8.0以下會使用DUIwebview, 大於等於8.0會使用DWKwebview。

所有的webview除了都實現了上述api之外,提供了一個載入網頁的便捷函數:

- (void)loadUrl: (NSString *) url;

您可以根據具體業務使用任意一個,不過一般情況下優先選用DWebview,它在新裝置上更省資源,效率更高。

DWebview還提供了一些其它api和屬性,具體請查看其標頭檔,需要特殊說明的是,有一個api:

- (id _Nullable) getXWebview;

它可以返回DWebview內部使用的真實webview, 值會是DUIwebview和DWKwebview的執行個體之一,您可以通過isKindOfClass來判斷,吃函數主要用於擴充DWebview,下面可以看一下loadRequest的大概實現:

- (void)loadRequest:(NSURLRequest *)request{      id webview=[self getXWebview];    if([webview isKindOfClass:[DUIwebview class]]){        [(DUIwebview *)webview loadRequest:request];    }else{        [(DWKwebview *)webview loadRequest:request];    }}
注意

DWebview已經實現 alert、prompt、comfirm對話方塊,您可以不做處理,也可以自訂。值得一提的是js 在調用alert函數正常情況下只要使用者沒有關閉alert對話方塊,js代碼是會阻塞的,但是考慮到alert 對話方塊只有一個確定按鈕,也就是說無論使用者關閉還是確定都不會影響js代碼流程,所以DWebview中在彈出alert對話方塊時會先給js返回,這樣一來js就可以繼續執行,而提示框等使用者關閉時在關閉即可。如果你就是想要阻塞的alert,可以自訂。而DWebview的prompt、comfirm實現完全符合ecma標準,都是阻塞的。

請不要手動設定DUIwebview的delegate屬性,因為DUIwebview在內部已經設定了該屬性,如果您需要自己處理頁面載入過程,請設定WebEventDelegate屬性。

 

混合開發Js bridge新秀-DSBridge iOS篇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.