要是 IOS 開發的哥們告訴大家說webview 和 本地交互只能通過 “攔截Url” 的方式。。。

要是 IOS 開發的哥們告訴大家說webview 和 本地交互只能通過 “攔截Url” 的方式。。。你可以告訴他們還可以 像android 一樣注入 JavaScriptInterface.


原文如下:

http://dukeland.hk/2013/01/28/adding-javascript-interface-to-uiwebview-like-android/


JANUARY 28, 2013

輕鬆加入 Javascript Interface 到 UIWebView 中(跟 Android 一樣方便)

最近在開發一個 iOS app,需要使用混合模式(native + WebView),當中有些部份需要 Javascript 和 Objective-C 雙向溝通,要在 Objective-C中使用 Javascript function 並不難,使用 UIWebView 中的 “stringByEvaluatingJavaScriptFromString” 就可以了,要在 Javascript 中使用 Objective-C 比較難一點點,需要 implement UIWebViewDelegate的 “shouldStartLoadWithRequest”。

Android 在這一方面做得很簡單,在 WebView 裏有一個 method 叫做 “addJavascriptInterface”,可以讓開發者自由加入 Javascript 的 Interface,在 Javascript 中就可以直接使用 Java 的 function,在 Objective-C 中我們可以複制一下這個模式嗎?

當然可以,不然我為什麼要寫這篇文章

市面上已經有一個挺方便的 class 可以用,就是這個 Native Bridge,然而用了之後你會發現有些問題;第一它要 return 數值到 Javascript 的話要用 async-style,這樣你的程式碼看起來會過份臃腫。第二讓 Javascript 使用的 function 要全部寫到 UIWebView 的 handleCall 中,用起上來不夠簡潔。讓我們來解決這個問題吧!

首先我們要繼承一下 UIWebView,並加入以下 method。

?
1
2
3
-(void) addJavascriptInterfaces:(NSObject*)interfaceWithName:(NSString*) name{
    [self.proxyDelegate addJavascriptInterfaces:interfaceWithName:name];
}

method signature 就跟 Android 裏的一樣,裏面會使用 proxy delegate 的 addJavascriptInterfaces,為什麼要用 proxy delegate 呢?因為要避免佔據了 UIWebView 的 delegate property 呀,不然其他用家怎樣使用它來 intercept 其他 request 呢!

Proxy Delegate 就是這個 library 的主角,它主要 implement 了兩個 method 來加入我們想要的功能,一是 webViewDidStartLoad,一是 shouldStartLoadWithRequest。

在 webViewDidStartLoad 時我們要把我們的 Javascript 注入到 UIWebView 中,這包括兩個部份。第一部份是我們的 Javascript 基本代碼,這包括了兩個 function,call() 用來 call Objective-C Interface 的 method,inject() 用來注入 Interface 內所有 method signature 到 Javascript 去。第二部份是我們 runtime 生成的 method signature,會使用 inject() 注入到 Javascript 中。

在 shouldStartLoadWithRequest 時我們要 intercept 一下,看看這個 request 是不是 easy-js: protocol,是的話我們就用 reflection 的方法去呼叫我們的 Objective-C Interface,並且把 return value 用 Javascript 再注入到 UIWebView 中,這樣我們便不用等到 request 完才用 async 的方法把 return value 傳到 UIWebView 去。

用文字解釋這個 library 實在不容易,大家還是看代碼更簡單

GitHub: EasyJSWebView

Sample project: EasyJSWebViewSample

使用方法:

1. 建立一個 Javascript Interface Class

?
1
2
3
4
5
6
7
8
9
@interfaceMyJSInterface:NSObject
 
-(void) test;
-(void) testWithParam:(NSString*) param;
-(void) testWithTwoParam:(NSString*) param AndParam2:(NSString*) param2;
 
-(NSString*) testWithRet;
 
@end

2. 把它加入到 WebView 裏

?
1
2
3
MyJSInterface*interface=[MyJSInterfacenew];
[self.myWebView addJavascriptInterfaces:interfaceWithName:@"MyJSTest"];
[interface release];

3. 在 Javascript 中可以直接使用了

?
1
2
3
4
5
MyJSTest.test();
MyJSTest.testWithParam("ha:ha");
MyJSTest.testWithTwoParamAndParam2("haha1","haha2");
 
varstr =MyJSTest.testWithRet();

更多其他例子請到 github 的 sample project 裏閱讀吧。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章