iOS 中 JavaScript 与 Native 交互


Image Origin From

Hybrid App 根本不是一个有争议的话题,在实际的开发中多多少少都会有这种交互式的开发。iOS 7之后加入了新的Framework,更加强化了这种交互。

自定义协议

之前比较流行的一种方法是自定义协议,链接里统一使用这种协议,然后在WebView的网络请求中拦截该协议,做出相应的事。

当然这里不一定要使用协议,可以在URL里写任意固定的规则,再去字符串匹配都可以的。但取scheme比较简单,比较起来性能也会好一些,比较通用。

1
2
3
4
wkt://course?id=1
# 类似的还有点评:
dianping://tuandeal?id=8091344&act=c&dealid=8091344&_utm=__n0k&_p=dummy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
var scheme = request.URL.scheme
if (scheme!.caseInsensitiveCompare("http") == NSComparisonResult.OrderedSame) {
return true
}
if (scheme!.caseInsensitiveCompare("wkt") == NSComparisonResult.OrderedSame) {
// 在这里调用解析方法
self.customRequestHandleWithUrl(request.URL)
return false
}
return true
}

如果需要Native来操作JavaScript,UIWebView提供了stringByEvaluatingJavaScriptFromString方法,它将Javascript代码嵌入到页面中运行,并将运行结果返回。

1
2
3
4
var returnValue = self.webView.stringByEvaluatingJavaScriptFromString("alert('Hello World!');")
# 调用
self.webView.stringByEvaluatingJavaScriptFromString("myFunction();")

有做过一个项目,Web端并未提供足够清晰的Function来操控,只好自己写上一段JS,然后在页面Load完之后Hack进去,通过这些新的Function来交互。

1
2
3
var filePath = NSBundle.mainBundle().pathForResource("demo", ofType: "js")
var content = String(contentsOfFile: filePath!, encoding: NSUTF8StringEncoding, error: nil)
self.webView.stringByEvaluatingJavaScriptFromString(content!)

PS:

  • JavaScript的执行时间不能超过10秒,否则UIWebView将停止执行脚本。
  • JavaScript分配的内存限制为10M,如果超过此限制,UIWebView将引发异常。

WebViewJavascriptBridge

如果觉得配置复杂,可以使用该库来简化配置。它供对JavaScript和Native都提供了一些方法来支持相互调用,并有回调。

具体用法参见:优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案

JavaScriptCore

JavaScriptCore Framework Reference

iOS 7中推出了新的JavaScript Core