iOS原生UIWebView与JS交互

​ 在iOS开发中,H5的嵌入可以通过UIWebView或者WKWebView。这两个都是继承UIView,来加载web数据的类。WKWebView是在iOS8苹果新推出的,加载速度快,占用内存较少,优点明显。但考虑到需要兼容iOS7以上版本,所以本篇主要说UIWebView的交互开发,后续会研究WKWebView和JavaScriptCore 的使用。

​ iOS平台JS与Native的交互需要遵循一定的协议,JS可以调用Native方法,其中方法可以是有参数的。Native也可以调用JS的方法,也是可以带参数的。

​ 本文主要讲利用 WebViewJavascriptBridge 实现交互操作的解决方案,从易用性,社区热度,可维护性方面考虑,都是非常具有优势,它能帮助我们优雅的实现OC与JS的交互, 非常方便简洁。

​ WebViewJavascriptBridge顾名思义,就相当于一座桥梁,两端连接了Obj-C和JavaScript。它提供了OC和JS互调的方法接口,方法在互调之前,我们需要向对方注册我们的方法列表。下面就开始实际操作

JS调用Native:

什么是js调用native?

简单来说就是通过js调用本地代码,举个例子来说就是在网页中有一个登录按钮,点击登录按钮,,具体的登录功能是由OC端实现的,即登录功能实现需要我们在工程里有一个类似loginMethod的函数去具体操作。

​ 原理是在UIWebView的代理方法中截取网页重定向字符串,字符串如果符合特定的格式(可以利用正则表达式去检查),就解析字符串,获取方法以及参数,然后再调用Native的方法。

下面是 WebViewJavascriptBridge 的使用 :

// 启用日志记录
[WebViewJavascriptBridge enableLogging];
// 初始化WebViewJavascriptBridge
_bridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
// `setWebViewDelegate`这个方法,可以将UIWebView的代理,从_webViewBridge中再传递出来,所以不需要为UIWebView设置代理
[_bridge setWebViewDelegate:self];

添加JS 要调用的 Native 功能,注册的 handler 是供 JS调用 Native 使用的,在JS中调用了 bridge.callHandler('scanClick') 方法将数据传给OC端,它将触发OC端 bridge registerHandler:@"scanClick"方法中的回调,如下:

[_bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"---------------------扫一扫-------------------------");
NSLog(@"data is : %@", data);
NSString *scanResult = @"http://www.baidu.com";
// 将结果返回给JS
responseCallback(scanResult);
}];
[_bridge registerHandler:@"shareClick" handler:^(id data, WVJBResponseCallback responseCallback) {
NSDictionary *tempDic = data;
NSString *title = [tempDic objectForKey:@"title"];
NSString *content = [tempDic objectForKey:@"content"];
NSString *url = [tempDic objectForKey:@"url"];
// 在这里执行分享的操作...
// 将分享的结果返回到JS中
NSString *result = [NSString stringWithFormat:@"分享成功:%@,%@,%@",title,content,url];
responseCallback(result);
}];
function scanClick() {
WebViewJavascriptBridge.callHandler('scanClick', {'foo': 'bar'}, function(response) {
alert('扫描结果:' + response);
document.getElementById("returnValue").value = response;
})
}
function shareClick() {
var params = {'title':'测试分享的标题','content':'测试分享的内容','url':'http://www.baidu.com'};
WebViewJavascriptBridge.callHandler('shareClick',params,function(response) {
alert(response);
document.getElementById("returnValue").value = response;
});
}

Native调用JS:

和JS调用OC的流程大致一样,还是需要与网页编写人员约定出一个事件名,然后在网页里面先注册这样一个事件并把实现体写好,等到我们OC去触发这个事件(比如点击按钮)就会去网页里面找到这个事件的实现体并执行。

iOS可以通过stringByEvaluatingJavaScriptFromString:方法直接调用html的JS方法。

下面是 WebViewJavascriptBridge 的使用 ,在OC端调用callHandler:@"testJSFunction"将数据传给JS,它将触发JS端注册的bridge.registerHandler('testJSFunction')方法中的回调

setupWebViewJavascriptBridge(function(bridge) {
bridge.registerHandler('testJSFunction', function(data, responseCallback) {
alert('JS方法被调用:' + data);
responseCallback('js执行过~~~');
})
})

OC端调用

// 如果不需要参数,不需要回调,可使用这个
[_bridge callHandler:@"testJSFunction"];
// 如果需要参数,不需要回调,使用这个
[_bridge callHandler:@"testJSFunction" data:@"一个字符串"];
// 如果既需要参数,又需要回调,使用这个
[_bridge callHandler:@"testJSFunction" data:@"一个字符串" responseCallback:^(id responseData) {
NSLog(@"调用完JS后的回调:%@", responseData);
}];

注:对于以上使用的监听方法名要和JS开发的人员约定好,必须保持一致。

模板替换

在加载html时替换模版中的特殊字符串,截取一部分模板文件代码如下:

<div id="vedioArea" class="vedio-area">
<img id="img_vedio_thumb"/>
<img id="img_start" src="./biz_video_list_play_icon_big.png"/>
</div>
<div id="contentDiv" style="padding:10px;word-break:break-all;">
<!--body-->
</div>

替换模板文件中的 然后插入 body 位置

// 插入 body 位置
NSRegularExpression *regexBody = [NSRegularExpression regularExpressionWithPattern:@"<!--body-->"
options:0
error:nil];
htmlString = [regexBody stringByReplacingMatchesInString:htmlString
options:0
range:NSMakeRange(0, htmlString.length)
withTemplate:bodyStr];

以上就是使用 WebViewJavascriptBridge 进行UIWebView与JS的交互的实际例子。

参考资料

热评文章