OC与webView相互调用
代码第一时间奉上
https://github.com/lailibo8/OCVSJS.git
在工作中经常遇到WebView与原生的页面的交互,以及互相传递参数,做参考使用
1、webViewJavascriptBridge
js调用OC
/* JS调用OC的API:访问相册 */
[self.bridge registerHandler:@"openCamera" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"需要%@图片", data[@"count"]);
UIImagePickerController *imageVC = [[UIImagePickerController alloc] init];
imageVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:imageVC animated:YES completion:nil];
}];
/* JS调用OC的API:弹窗互相传递参数
data JS传递给OC的参数值
responseCallback 传递给JS的参数值
*/
[self.bridge registerHandler:@"showBackBtnIcon" handler:^(id data, WVJBResponseCallback responseCallback) {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"%@",data] message:@"世界真好" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
responseCallback(@"传给JS参数");
}];
[vc addAction:cancelAction];
[vc addAction:okAction];
[self presentViewController:vc animated:YES completion:nil];
}];
[self.bridge registerHandler:@"showAlertTest" handler:^(id data, WVJBResponseCallback responseCallback) {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"%@",data] message:@"谢谢简书" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
responseCallback(@"你看看,我给传给JS参数,够不够,不够我再给你多传");
}];
[vc addAction:cancelAction];
[vc addAction:okAction];
[self presentViewController:vc animated:YES completion:nil];
}];
OC调用JS
// 调用JS中的API
[self.bridge callHandler:@"getJianshuInfo" data:@{@"userId":@"行走在北方"} responseCallback:^(id responseData) {
NSString *userInfo = [NSString stringWithFormat:@"%@",responseData[@"JsonMessage"]];
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"从网页端获取的用户信息" message:userInfo preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[vc addAction:cancelAction];
[vc addAction:okAction];
[self presentViewController:vc animated:YES completion:nil];
}];
// 调用JS中的API
[self.bridge callHandler:@"alertWindow" data:@"调用了js中的Alert弹窗!" responseCallback:^(id responseData) {
NSLog(@"=====%@",[responseData objectForKey:@"JsonMessage"]);
}];
这是JS的代码
//***********************获取JS的信息
bridge.registerHandler('getJianshuInfo', function(data, responseCallback) {
var responseData = { 'JsonMessage' : '这么棒你已经获取了,行走在北方' }
responseCallback(responseData)
alert(data.userId)
})
bridge.registerHandler('alertWindow', function(data, responseCallback) {
alert(data)
var responseData = { 'JsonMessage' : '给你点什么信息呢,就这样吧,算了吧' }
responseCallback(responseData)
})
2、WKScriptMessageHandler
OC调用JS的代码
NSString *JSResult = [NSString stringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
//OC调用JS
[self.webView evaluateJavaScript:JSResult completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@", error);
}];
JS代码
function shareClick(){
window.webkit.messageHandlers.Share.postMessage({title:'测试分享的标题',content:'测试的分享内容',url:'https://www.jianshu.com/u/82217813c143'})
}
JS调用OC代码
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name caseInsensitiveCompare:@"jsToOc"] == NSOrderedSame) {
[JXTAlertView showToastViewWithTitle:message.name message:message.body duration:2 dismissCompletion:nil];
}
if ([message.name isEqualToString:@"Share"]) {
[self ShareWithInformation:message.body];
} else if ([message.name isEqualToString:@"Camera"]) {
[self camera];
}
}
//为了防止循环引用
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"jsToOc"];
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"Camera"];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[_webView.configuration.userContentController removeScriptMessageHandlerForName:@"jsToOc"];
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"Camera"];
}
- (void)payAction:(NSURL *)URL
{
NSArray *params =[URL.query componentsSeparatedByString:@"&"];
NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
for (NSString *paramStr in params) {
NSArray *dicArray = [paramStr componentsSeparatedByString:@"="];
if (dicArray.count > 1) {
NSString *decodeValue = [dicArray[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[tempDic setObject:decodeValue forKey:dicArray[0]];
}
}
NSString *orderNo = [tempDic objectForKey:@"order_no"];
long long amount = [[tempDic objectForKey:@"amount"] longLongValue];
NSString *subject = [tempDic objectForKey:@"subject"];
NSString *channel = [tempDic objectForKey:@"channel"];
// 支付操作
// 将支付结果返回给js
NSString *jsStr = [NSString stringWithFormat:@"payResult('%@', 1)",@"支付成功"];
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
}
3、URL拦截
JS调用OC
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURL *URL = navigationAction.request.URL;
NSString *scheme = [URL scheme];
if ([scheme isEqualToString:@"haleyaction"]) {
[self handleCustomAction:URL];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)handleCustomAction:(NSURL *)URL
{
NSString *host = [URL host];
if ([host isEqualToString:@"scanClick"]) {
NSLog(@"扫一扫");
} else if ([host isEqualToString:@"shareClick"]) {
[self share:URL];
} else if ([host isEqualToString:@"getLocation"]) {
[self getLocation];
} else if ([host isEqualToString:@"setColor"]) {
[self changeBGColor:URL];
} else if ([host isEqualToString:@"payAction"]) {
[self payAction:URL];
} else if ([host isEqualToString:@"shake"]) {
[self shakeAction];
} else if ([host isEqualToString:@"goBack"]) {
[self goBack];
}
}
JS代码
function scanClick() {
asyncAlert(arr);
loadURL("haleyAction://scanClick");
}
function shareClick() {
loadURL("haleyAction://shareClick?title=测试分享的标题&content=测试分享的内容&url=http://www.baidu.com");
}
function locationClick() {
loadURL("haleyAction://getLocation");
}
function setLocation(location) {
asyncAlert(location);
document.getElementById("returnValue").value = location;
}
function getQRCode(result) {
asyncAlert(result);
document.getElementById("returnValue").value = result;
}
function colorClick() {
loadURL("haleyAction://setColor?r=67&g=205&b=128&a=0.5");
}
function payClick() {
loadURL("haleyAction://payAction?order_no=201511120981234&channel=wx&amount=1&subject=粉色外套");
}
区别
1.WebViewJavaScriptBridge缺点就是要固定的加入相关代码,JS端代码要在固定的函数内添加,使用拦截协议URL的方式传递参数需要把参数拼接在后面,遇到要传递的参数有特殊字符,例如& 、= 、?等解析容易出问题;
2.WKWebview-MessageHandler在JS中写起来更简单一点,JS传递参数更方便,减少参数中特殊字符引起的错误,WKWebView在性能、稳定性方面更加强大;
3.URL拦截使用起来比较简单,特殊字符串需要处理下。
网友评论