美文网首页iOS 技巧
OC与JS相互调用和传值

OC与JS相互调用和传值

作者: 行走在北方 | 来源:发表于2020-08-17 17:45 被阅读0次

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拦截使用起来比较简单,特殊字符串需要处理下。

推荐这篇写的好
https://github.com/Haley-Wong/JS_OC

相关文章

网友评论

    本文标题:OC与JS相互调用和传值

    本文链接:https://www.haomeiwen.com/subject/igbqjktx.html