移動(dòng)技術(shù)發(fā)展了七八年毁涉,開(kāi)發(fā)人員永遠(yuǎn)有個(gè)跨平臺(tái)的夢(mèng)饼齿。從最開(kāi)始的 Web App 被人詬病體驗(yàn)差买乃,ReactNative姻氨,Weex 等技術(shù)又有很多難以平復(fù)的坑,包括現(xiàn)在的 Flutter 也有很多問(wèn)題待解決剪验,跨平臺(tái)的夢(mèng)想很美好肴焊,現(xiàn)實(shí)卻總有這樣那樣的瑕疵前联。移動(dòng)開(kāi)發(fā)發(fā)展到今天,我認(rèn)為最好的跨平臺(tái)技術(shù)還是 H5 + Native 的混合開(kāi)發(fā)模式抖韩。隨著前端技術(shù)的飛速發(fā)展蛀恩,如今可以依靠各種技術(shù)和工具對(duì)前端進(jìn)行優(yōu)化,使其在移動(dòng)端的體驗(yàn)更接近原生水平茂浮。
我們?cè)谧龌旌祥_(kāi)發(fā)(Hybrid App)時(shí)双谆,絕對(duì)繞不開(kāi) JavaScript 與 Native(iOS & Android)之間的交互問(wèn)題。現(xiàn)在主流的交互框架有 WebViewJavascriptBridge席揽,它可能是最早的 iOS 與 JavaScript 橋接庫(kù)顽馋,該庫(kù)優(yōu)點(diǎn)是接口簡(jiǎn)單好用,不用往 HTML 中引入額外的 js 文件幌羞,缺點(diǎn)是只支持 iOS寸谜,同一個(gè)項(xiàng)目還要為 Android 尋找一個(gè)對(duì)應(yīng)的橋接庫(kù),另一個(gè)問(wèn)題是對(duì)交互接口沒(méi)有管理属桦,大多數(shù)情況下我們把接口都寫到一個(gè) Controller 中的熊痴,造成代碼堆積,接口不易維護(hù)聂宾。近幾年還有一個(gè)比較好的橋接庫(kù)是 DSBridge-IOS果善,這個(gè)庫(kù)相比 WebViewJavascriptBridge 的優(yōu)勢(shì)是支持 iOS 與 Android,接口支持以類的方式管理系谐,但是使用時(shí)需要往 HTML 中引入一個(gè) js 文件巾陕,3.0 新版本只支持 WKWebView,其實(shí)現(xiàn)方式是繼承了 WKWebView纪他,所以使用時(shí)要使用其改造后的 DWKWebView鄙煤,我本人不喜歡這種對(duì) WebView 的侵入方式。
我在其兩個(gè)庫(kù)的基礎(chǔ)之上又造了一個(gè)輪子茶袒,這就是 WebViewJsBridge-iOS梯刚,它首先支持 iOS 與 Android 兩個(gè)端,接口與 WebViewJavascriptBridge 基本一樣薪寓,同樣支持以類的方式管理交互接口乾巧,同樣需要引入一個(gè) js 文件(在 1.1.0 版本中可以不引用這個(gè) js 文件),同時(shí)支持 UIWebView 和 WKWebView预愤,沒(méi)有用繼承 WebView 這種侵入方式實(shí)現(xiàn)功能。
以下是 WebViewJsBridge-iOS 的使用文檔供大家參考:
WebViewJsBridge-iOS
WebViewJsBridge-iOS 是 HTML5 和 UIWebView & WKWebView 之間用于通訊的工具庫(kù)咳胃。
WebViewJsBridge-Android:https://github.com/al-liu/WebViewJsBridge-Android
它的特點(diǎn)是跨平臺(tái)植康,支持 iOS,Android展懈,JavaScript销睁,接口統(tǒng)一供璧,簡(jiǎn)單易用。工具庫(kù)的實(shí)現(xiàn)對(duì) WebView 無(wú)侵入性冻记。使用以類的方式來(lái)管理通信的接口睡毒,每個(gè)接口的實(shí)現(xiàn)類對(duì)應(yīng)唯一的命名空間,如 ui.alert冗栗,ui 對(duì)應(yīng)一個(gè)實(shí)現(xiàn)類的命名空間演顾,alert 是該實(shí)現(xiàn)類的一個(gè)實(shí)現(xiàn)方法。在 1.1.0 版本中隅居, H5 可以不引入 hcJsBridge.js 文件钠至。
下面這張圖幫助理解它們之間的關(guān)系:
系統(tǒng)版本要求
如果使用 UIWebView 則支持 iOS7 及以上的系統(tǒng)版本。
如果使用 WKWebView 則支持 iOS8 及以上的系統(tǒng)版本胎源。
安裝
CocoaPods
CocoaPods 是 Cocoa 項(xiàng)目的依賴管理器棉钧,使用方法和安裝步驟請(qǐng)參考 CocoaPods 的官網(wǎng)。使用 CocoaPods 整合 WebViewJsBridge-iOS 到你的項(xiàng)目中涕蚤,需要指定如下內(nèi)容到你的 Podfile 文件:
platform :ios, '8.0'
target 'TargetName' do
pod 'HCWebViewJsBridge', '~> 1.1.0'
end
然后宪卿,運(yùn)行如下命令:
$ pod install
手動(dòng)安裝
下載 HCWebViewJsBridge 的源代碼,并添加到自己的項(xiàng)目中即可使用万栅。
引入 HCWebViewJsBridge 的 js 文件
在 html 文件中 <script>引入 hcJsBridge.js</script>
佑钾。
注意: 1.1.0 版本 H5 可以不引入 hcJsBridge.js 文件,但使用方法有少許差異申钩,后面有介紹次绘。
Example 的說(shuō)明
/Example/iOS Example
文件夾下提供完整使用示例,包括基礎(chǔ)的調(diào)用演示和進(jìn)階用法撒遣,如邮偎,使用 UIImagePickerController
調(diào)用相機(jī)拍攝一張圖片,使用 NSURLSession
發(fā)起一個(gè) GET 請(qǐng)求义黎。
使用方法
初始化原生的 WebViewJsBridge 環(huán)境
UIWebView
如果 H5 引入 hcJsBridge.js禾进,則使用下面這個(gè)初始化方法。
_bridge = [HCWebViewJsBridge bridgeWithWebView:self.webView];
如果 H5 不引入 hcJsBridge.js廉涕,則使用下面這個(gè)初始化方法泻云。
_bridge = [HCWebViewJsBridge bridgeWithWebView:self.webView injectJS:YES];
WKWebView
如果 H5 引入 hcJsBridge.js,則使用下面這個(gè)初始化方法狐蜕。
_bridge = [HCWKWebViewJsBridge bridgeWithWebView:self.wkWebView];
如果 H5 不引入 hcJsBridge.js宠纯,則使用下面這個(gè)初始化方法。
_bridge = [HCWKWebViewJsBridge bridgeWithWebView:self.wkWebView injectJS:YES];
原生注冊(cè)接口實(shí)現(xiàn)類供 HTML5 調(diào)用
UIJsApi *uiApi = [UIJsApi new];
[_bridge addJsBridgeApiObject:uiApi namespace:@"ui"];
RequestJsApi *requestJsApi = [RequestJsApi new];
[_bridge addJsBridgeApiObject:requestJsApi namespace:@"request"];
UIJsApi 實(shí)現(xiàn)類:
- (void)alert:(NSDictionary *)data callback:(HCJBResponseCallback)callback {
callback(@"native api alert’callback.");
}
// 接口實(shí)現(xiàn)類支持四種方法簽名:
// 1. 有參數(shù)层释,有回調(diào)
- (void)test1:(NSString *)data callback:(HCJBResponseCallback)callback {
NSLog(@"Js call native api test1, data is:%@", data);
callback(@"native api test1’callback.(備注:漢字測(cè)試)");
}
// 2. 有參數(shù)婆瓜,無(wú)回調(diào)
- (void)test2:(NSDictionary *)data {
NSLog(@"Js native api:test2, data is:%@", data);
}
// 3. 無(wú)參數(shù),無(wú)回調(diào)
- (void)test3 {
NSLog(@"Js native api:test3");
}
// 4. 無(wú)參數(shù),有回調(diào)
- (void)test4:(HCJBResponseCallback)callback {
NSLog(@"Js native api:test4");
callback(@"native api test4'callback.(備注:漢字測(cè)試)");
}
原生調(diào)用 HTML5 接口
[_bridge callHandler:@"testCallJs" data:@{@"foo": @"bar"} responseCallback:^(id _Nonnull responseData) {
NSLog(@"testCallJs callback data is:%@", responseData);
}];
初始化 HTML5 的 WebViewJsBridge 環(huán)境
如果 H5 引入 hcJsBridge.js廉白,則使用下面的方式引入个初。
<!DOCTYPE html>
<html>
<head>
...
<script src="./hcJsBridge.js"> </script>
</head>
...
</html>
如果 H5 不引入 hcJsBridge.js,則使用下面這個(gè)方法注冊(cè)接口猴蹂。
// 在這個(gè) window._hcJsBridgeInitFinished 全局函數(shù)中等待 bridge 初始化完成院溺,然后注冊(cè)接口,初始調(diào)用磅轻。
window._hcJsBridgeInitFinished = function(bridge) {
bridge.registerHandler("test1", function(data, callback) {
callback('callback native,handlename is test1');
})
bridge.callHandler('ui.test3');
}
HTML5 注冊(cè)接口供原生調(diào)用
hcJsBridge.registerHandler("testCallJs", function(data, callback) {
log('Native call js ,handlename is testCallJs, data is:', data);
callback('callback native, handlename is testCallJs');
})
HTML5 調(diào)用原生接口
var data = {foo: "bar"};
hcJsBridge.callHandler('ui.alert', data, function (responseData) {
log('Js receives the response data returned by native, response data is', responseData);
})
開(kāi)啟 debug 日志
開(kāi)啟 debug 日志珍逸,將打印一些調(diào)用信息,輔助排查問(wèn)題瓢省。debug 日志默認(rèn)不開(kāi)啟弄息,release 模式下屏蔽 debug 日志,但不屏蔽 error 日志勤婚。
[_bridge enableDebugLogging:YES];
License
WebViewJsBridge-iOS 使用 MIT license 發(fā)布摹量,查看 LICENSE 詳情。