DSBridge是目前地球上最好的IOS/Android javascript bridge. 沒有之一 !
依然是部落格搬家,若已閱讀過,請跳過。
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 ,相信你看完之後會回來的。
DSBridge雖說簡單,但為了讓你瞭然於胸,還是給出官方解釋:
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介面約定如下:
- 返回值型別存在時為NSString、不存在時為void。
- 引數以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對話方塊,您可以不做處理,也可以自定義。
請不要手動設定DUIwebview的delegate屬性,因為DUIwebview在內部已經設定了該屬性,如果您需要自己處理頁面載入過程,請設定WebEventDelegate屬性。
拉票
如果你覺得不錯,麻煩star一下哦!多謝支援?。如有問題,歡迎反饋,wechat: Demons-du