美文网首页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