緣由閑扯
話說WebView 與 Native的交互并不復(fù)雜挺物;似乎需不需要什么封裝,項(xiàng)目之初也是這么想的,只是需求的增加湘换,UIWebView和WKWebView的混合使用(WKWebView性能好些医窿,只是確實(shí)由不少問題參見 <a >WKWebViewTips</a>伸但, 補(bǔ)充:修改WKWebView的contentInset會(huì)導(dǎo)致位置計(jì)算出錯(cuò),導(dǎo)致js點(diǎn)擊出現(xiàn)問題)留搔;代碼變得也就難以維護(hù)更胖;話說不造輪子的廚師不是好裁縫;開源的項(xiàng)目不少隔显,研究了下却妨,重新設(shè)計(jì),然后有了 <a >WebViewBridge.Swift</a>
簡(jiǎn)介
WebView與Native橋并不是一個(gè)新的話題, 在很早以前就有實(shí)現(xiàn)了, 也有很好的實(shí)現(xiàn).比如 <a >Cordova(PhoneGap)</a>, <a >WebViewJavascriptBridge</a>橋本身的技術(shù)并不困難, 實(shí)現(xiàn)也都大同小異, 既然已經(jīng)有項(xiàng)目 <a >Cordova(PhoneGap)</a>, <a >WebViewJavascriptBridge</a>, 那還有必要重復(fù)再造輪子么?
- Cordova-ios: 本身是一個(gè)很了不起的項(xiàng)目, 提供了多個(gè)平臺(tái), 對(duì)于 Hybrid App而言, 是一個(gè)很好的選擇;如果你編寫的不是Hybrid App, 只是想簡(jiǎn)單的集成 bridge這個(gè)功能, Cordova 就顯得過于復(fù)雜了, 不方面集成, 另外暫時(shí)也無 swift 版本的
- WebViewJavascriptBridge: 也很不錯(cuò), 同時(shí)提供了 iOS, android 版本, 集成也簡(jiǎn)單方便. 有以下幾點(diǎn)不足:
- UIWebView/WKWebView: 采用的舊式的 iframe 方式來實(shí)現(xiàn), 集成相對(duì)麻煩
- 沒有提供 Swift 版本
WebViewBridge.Swift 給你提供了另一種可能, 與其他相比由以下優(yōu)點(diǎn):
- 采用 JavaScriptCore, 棄用iframe括眠,使用更簡(jiǎn)單 (并非完全棄用iframe, 在webViewDidFinishLoad之前可能仍會(huì)使用iframe)
- 全 Swift 實(shí)現(xiàn)
WebViewBridge.Swift 是你的一個(gè)不錯(cuò)的選擇.
此外: 對(duì)于此外常見的 webview點(diǎn)擊下載圖片, 實(shí)例代碼中頁給出了實(shí)現(xiàn).
(注意實(shí)例代碼中, 下載緩存圖片代碼是有bug的,可以考慮使用第三方圖片庫, 比如 <a >Kingfisher</a>)
前提: 為WebView和html建立橋
1 給 UIWebView/WKWebView 建立橋
let webView = WKWebView()
let bridge = ZHWebViewBridge.bridge(webView)
- Note: 對(duì)于 UIWebView 需要注意一下事情
- 拷貝 bridge.js 代碼到你的html文件中
- 需要主動(dòng)調(diào)用 bridge.teardown() 用于釋放對(duì)你的 UIWebView的強(qiáng)引用
原生代碼與 JS 的相互交互
1, 原生代碼調(diào)用 js handler
a, 在你的html中或業(yè)務(wù) js 中 添加 js handler
ZHWVBridge.Core.registerJsHandler(
"Device.updateAppVersion",
function (version) {
document.getElementById("native-version-container").textContent = version;
return "js get version: " + version;
});
- 說明: ZHWVBridge.Core.registerJsHandler(handlerName, callback)
b, 原生代碼調(diào)用 js handler
bridge.callJsHandler(
"Device.updateAppVersion",
args: ["1.2"],
callback: { (data:AnyObject?) in
// here data should be "js get version: 1.2"
...
})
- 說明: bridge.callJsHandler(handlerName, 傳遞給js的參數(shù)數(shù)組, callback)
2, Js 調(diào)用原生 handler
a, 原生代碼中, bridge 注冊(cè) native handler
bridge.registerHandler("Image.updatePlaceHolder") { (args:[AnyObject]) -> (Bool, [AnyObject]?) in
return (true, ["place_holder.png"])
}
b, js 調(diào)用原生 handler
ZHWVBridge.Core.callNativeHandler(
"Image.updatePlaceHolder",
[],
function(placeHolder) {
var items = document.getElementsByTagName('img');
for (var i = 0, count = items.length; i < count; ++i) {
var item = items[i];
if (item.src.toLocaleLowerCase() == "file:///default_cover") {
item.src = placeHolder;
}
}
});
- 說明: ZHWVBridge.Core.callNativeHandler(handlerName, 傳遞給原生handler的參數(shù)數(shù)組, 成功回調(diào), 失敗回調(diào))