前言
在iOS原生應用程序加載網頁來實現部分界面或功能已不是什么稀奇的事了。很多應用都使用了HTML+CSS+Javascript+Native APP的方式來開發,如Fackbook、微信和支付寶等。采用這種開發模式具有明顯的好處:
- 跨平台,iOS、Android都可使用,write once run anywhere。
- 方便實現復雜的界面,使用前台技術可實現很炫的界面。
- 升級方便,修改程序后不用審核即可更新用戶程序。
當然,這也面臨着一個問題,那就是怎么實現原生程序和Web頁面交互,也即Objective-C(Swift)與JavaScript交互。iOS SDK中的UIWebView和WKWebView都可以方便的實現Objective-C(Swift)與JavaScript交互。同時,GitHub上的WebViewJavascriptBridge使得交互變得更為輕松。本文將介紹WebViewJavascriptBridge的使用方法。
准備
在GitHub上下載WebViewJavascriptBridge,里面包含WebViewJavascriptBridge源代碼和使用例子。使用前把文件夾WebViewJavascriptBridge拖入項目即可。
WebViewJavascriptBridge可應用於UIWebView和WKWebView。WKWebView是iOS 8引入的一個新的框架——WebKit.
使用
使用WebViewJavascriptBridge一般會有以下流程:
- 初始化
- 注冊可調用的函數
- 發送消息、調用函數
當然,還必須加載一個網頁。
初始化的時候需要提供一個函數/Block,當發送消息給另一個語言時(如Objective-C調用[bridge send:(id)data]向JavaScript發送消息),會執行這個函數/Block。
同時,只有注冊的函數才能供另一個語言調用。
Objective-C
導入頭文件#import "WebViewJavascriptBridge.h"
申明屬性 @property WebViewJavascriptBridge* bridge;
如果使用WKWebView,則使用如下方式:
導入頭文件#import "WKWebViewJavascriptBridge.h"
申明屬性 @property WKWebViewJavascriptBridge* bridge;
使用UIWebView/WKWebView初始化
//webView可以是UIWebView或WKWebView
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback)
{
NSLog(@"Received message from javascript: %@", data);
responseCallback(@"Right back atcha");
}];
在JavaScript中的bridge調用send方法后,會執行handler的block。
注冊JavaScript可調用的函數
[self.bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback)
{
NSLog(@"testObjcCallback called: %@", data);
responseCallback(@"Response from testObjcCallback");
}];
在JavaScript中的bridge調用testObjcCallback方法后,會執行該handler的block。
調用JavaScript方法
//無回調直接調用
[self.bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];
//有回調調用
id data = @{ @"greetingFromObjC": @"Hi there, JS!" };
[self.bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response)
{
NSLog(@"testJavascriptHandler responded: %@", response);
}];
當使用有回調調用方法時,會把block傳入JavalockScript方法,JavaScript代碼可執行該block(JavaScript的調用方法見下方)。
向JavaScript發送消息
[self.bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response)
{
NSLog(@"sendMessage got response: %@", response);
}];
發送消息與調用方法類似,相當調用一個特殊函數(該函數在JavaScript代碼中初始化時設置,見下方)。
加載網頁
//加載本地網頁
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"web" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[self.webview loadHTMLString:appHtml baseURL:baseURL];
//加載遠程網頁
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webview loadRequest:request];
JavaScript
添加監聽
function connectWebViewJavascriptBridge(callback)
{
if (window.WebViewJavascriptBridge)
{
callback(WebViewJavascriptBridge)
}
else
{
document.addEventListener('WebViewJavascriptBridgeReady', function(event)
{
callback(WebViewJavascriptBridge)
}, false)
}
}
connectWebViewJavascriptBridge(init);
初始化
初始化要在添加監聽之后進行。初始化時需要傳入一個函數,當Objective-C代碼發送消息調用[bridge send:(id)data]或[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]時會執行此函數。
function recieved(message, responseCallback)
{
log('JS got a message', message)
var data =
{
'Javascript Responds': 'Wee!'
}
log('JS responding with', data)
responseCallback(data)
}
function init(bridge)
{
bridge.init(recieved);
}
注冊Objective-C可調用的函數
function testJavascript(data, responseCallback)
{
log('ObjC called testJavascriptHandler with', data)
var responseData =
{
'Javascript Says': 'Right back atcha!'
}
log('JS responding with', responseData)
responseCallback(responseData)
}
bridge.registerHandler('testJavascriptHandler', testJavascript);
注冊后在Objective-C代碼中就可調用該函數(調用方法見上述)。
調用Objective-C方法
function callObjC()
{
gbridge.callHandler('testObjcCallback',
{
'foo': 'bar'
},
function(response)
{
log('JS got response', response)
});
}
Objective-C會執行以名稱testObjcCallback注冊的block。
發送消息
與調用函數類似,會調用Objective-C中初始化時傳入的block。
function sendMessage()
{
var data = 'Hello from JS button'
gbridge.send(data, function(responseData)
{
log('JS got response', responseData)
})
}
結語
可以說WebViewJavascriptBridge的使用是如此簡單,以至不需要太多的筆墨。當然WebViewJavascriptBridge也是很強大的,它能結合WebApp和Native APP並充分發揮各自的優勢。
原文鏈接: http://zh.5long.me/2015/ios-objective-c-javascript-bridge/
版權聲明:自由轉載-非商用-保持署名 | Creative Commons BY-NC 4.0
