要是 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
@interface MyJSInterface: NSObject
 
-( void ) test;
-( void ) testWithParam:( NSString *) param;
-( void ) testWithTwoParam:( NSString *) param AndParam2:( NSString *) param2;
 
-( NSString *) testWithRet;
 
@end

2. 把它加入到 WebView 裏

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

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

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

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


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值