大多数的 App 都会有嵌入网页的做法,因此可能就会遇到原生与网页里的交互的场景。交互无非就两种情况,要么是 Objective-C (以下简称 objc ) 调用 Javascript (以下简称 js) 的方法,要么 js 调用原生的方法。
考虑到效率和拓展维护,在开发过程中我选择了一个被开发者广泛使用的一个优秀的开源库 WebViewJavascriptBridge 。使用起来也比较简单,但是需要前端工程师的配合,在 js 里添加代码。
iOS 端:
1、初始化
self.webViewBridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[self.webViewBridge setWebViewDelegate:self];
这里需要注意的是,初始化方法要写到 UIWebView 的初始化之后。
2、js 调用 objc
既然 js 需要调用我们,我们要提前准备好方法。下面在我们的代码中先注册一个方法供 js 调用。
[self.webViewBridge registerHandler:@"shareClick" handler:^(id data, WVJBResponseCallback responseCallback) {
// Do Share
responseCallback();//可选 :分享完成后,可以选择通知 js 端。
}];
这里的 “shareClick” 可以认为是一个 key, js 通过这个 key 回调我们的方法。
你可以对每个方法设置一个不同的 key ,在每个方法的回调里单独执行某个行为。比如上面的是分享,你可以再次注册一个 “openPhotoLibraryClick”
[self.webViewBridge registerHandler:@"openPhotoLibraryClick" handler:^(id data, WVJBResponseCallback responseCallback) {
// Open You PhotoLibraryClick
responseCallback();//可选 :分享完成后,可以通知 js 端。
}];
当然你也可以只注册一个方法,通过 js 传过来的 data 来区分不同的方法。比如:
[self.webViewBridge registerHandler:@"jsBridgeCall" handler:^(id data, WVJBResponseCallback responseCallback) {
if ([data isKindOfClass:[NSDictionary class]]) {
NSDictionary *dataDict = (NSDictionary *)data;
if([dataDict[@"type"] isEqualToString:SHARE_TYPE]){
// Do Share
}else if([dataDict[@"type"] isEqualToString:SHARE_OPEN_PHTOTLIBRARY]){
// Open You PhotoLibraryClick
}
}
responseCallback();//可选 :分享完成后,可以通知 js 端。
}];
具体方案,要综合项目需求考虑,和前端工程师协商好就行。
3、objc 调用js
我们调用 js ,那 js 中自然也已经注册了一个方法供我们调用,我们同样只需要知道该方法的 key 即可,这里你可以根据具体情况选择是否需要传值,是需要 js的通知 回调:
//无值 无回调
[self.webViewBridge callHandler:@"finishedShare"];
//无回调
[self.webViewBridge callHandler:@"finishedShare" data:@{@"key":@"value"}];
//有传值 有回调
[self.webViewBridge callHandler:@"finishedShare" data:@{@"key":@"value"} responseCallback:^(id responseData) {
// js 完成调用后,如果有回调,可以在这里监听。
}];
至于选择写多个 callHandler 来区分不同的方法,还是一个通用的 callHandler ,通过我们传递给 js 的 type 来区分,同上所述。
js 端
1、定义对接函数(拷贝该方法到 js 里)
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
2、js 调用 objc
上文中,objc 已经 registerHandler 了 key 为 "shareClick" 的方法。因此 js 按照 key 值,就可以调用了:
var params = {'key':'value'};
window.WebViewJavascriptBridge.callHandler('shareClick', params);
window.WebViewJavascriptBridge.callHandler('shareClick',params,function(response) {
//如果 objc 端添加了回调,那么,回执行这里面的代码块
alert(response);
});
3、objc 调用 js
objc 调用 js 需要 js 先注册方法,objc 通过key去调用。
setupWebViewJavascriptBridge(function(bridge) {
bridge.registerHandler('finishedShare', function(data, responseCallback) {
//可选,可在执行完js的动作后,通知 objc
responseCallback('js执行过了');
})
})
总结:Objctive-C 与 Javascript 的相互调用,在 WebViewJavascriptBridge 的包装下,变得非常简单。总结下来就是:如果是 objc 调用 js ,那么 js注册方法(registerHandler),objc 调用方法(callHandler)。反之,objc 注册方法(registerHandler),js 调用方法(callHandler)。
网友评论