美文网首页iOS新手学习
iOS原生与Vue的方法交互

iOS原生与Vue的方法交互

作者: NinJaLife | 来源:发表于2019-03-20 18:11 被阅读0次

    最近公司很多项目涉及到在原生中嵌入H5的需求,h5多为vue页面,第一个项目使用的UIWebView加载,第二个项目使用WKWebView,转为WK的原因是因为前者对vue的兼容总会有些瑕疵,后者是苹果主推的控件,像微信这种巨头也在17年3月1号起正式启用WK,用它必有原因的,在此并不陈诉。用起来还是不是很熟,虽然简单但是细节较多,故记录提醒自己,也希望可以帮到其他人。项目中难免遇到两者选其一的时候,与web交互总会出现一些无法预知的问题,有时候UIWebView没有问题WKWebView出问题,反之亦然。
    此篇介绍了两者与vue交互的粗略方法。

    我们写好一个vue网页片段

    <el-button type="primary" id="one" v-on:click="OCcallJSClick()">OC调用JS方法</el-button>
    <el-button type="primary" id="two" v-on:click="clickVUE('我是网页的数据')">JS调用OC方法</el-button>
    

    注意:我们如果是在局域网内测试,比如本文,vue npm run dev后的网址是 localhost:8080/#/,所谓localhost其实是本机的ip地址,我们要保证手机和电脑在同一个局域网内,并且,我们需要在vue中稍作修改,在工程文件夹config下index.js中 ,把host:'localhost'改成0.0.0.0,这样在ios中填写网址时,把0.0.0.0换成pc端ip地址就可以在手机上访问这个网页了。


    UIWebView

    先看老家伙

    UIWebView *web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2)];
    self.webview = web;
    //这里换成pc端ip地址
    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://192.168.31.127:8082/#/"]];
    [web loadRequest:req];
    [(UIScrollView *)[[web subviews] objectAtIndex:0] setBounces:NO];
    web.scalesPageToFit = NO;
    web.delegate = self;
    [self.view addSubview:web];
    

    入正题;

    JS调用OC 并传参数给OC使用

    要实现原生与网页的交互,我们使用苹果自带的框架 <JavaScriptCore/JavaScriptCore.h> iOS7后引入的新框架。

    并且我们在网页加载完成后创建这个工具实例

    // 当页面开始加载的时候调用
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        self.jsContext = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //括号内的方法需与vue中的方法相同
        self.jsContext[@"JScallOCClick"] = ^(NSString *str) {
            NSLog(@"+++++++JScallOCClick+++++++");
            return [self jsCallOC:str];
        };
    }
    
    //注意,这里vue响应的是clickVUE方法,JScallOCClick是在这个方法内部,直接去响应这个方法是无效的
    clickVUE(b){
          JScallOCClick(b);
        },
    

    原生view中创建一个Button,然后相应方法,调用JS

        self.view.backgroundColor = [UIColor lightGrayColor];
        self.ocButton = [UIButton buttonWithType:UIButtonTypeCustom];
        self.ocButton.frame = CGRectMake(30, SCREEN_HEIGHT - 200, SCREEN_WIDTH - 60, 50);
        [self.ocButton setTitle:@"OC按钮调用JS代码" forState:UIControlStateNormal];
        [self.ocButton setBackgroundColor:[UIColor redColor]];
        [self.ocButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:self.ocButton];
    
    - (void)buttonClick:(UIButton *)sender
    {
         //此方法名称必须与vue中的方法相同 括号内携带参数
        NSString *textJS = [NSString stringWithFormat:@"OCcallJSClick('%@')",@"我是参数"];
        [self.jsContext evaluateScript:textJS];
    }
    

    OC调用JS 并传参数给JS使用

    //这里可以直接调用,绑定vue的事件  弹出ios传来的字符串
    OCcallJSClick(a){
          alert(a);
          console.log(a);
        },
    

    这里需要注意的是 oc调用js需要事先把这个方法暴露在外部 将方法名字挂载在mounted处

    mounted(){
        window.OCcallJSClick = this.OCcallJSClick;
      },
    

    ios中创建button,并绑定事件

        self.view.backgroundColor = [UIColor lightGrayColor];
        self.ocButton = [UIButton buttonWithType:UIButtonTypeCustom];
        self.ocButton.frame = CGRectMake(30, SCREEN_HEIGHT - 200, SCREEN_WIDTH - 60, 50);
        [self.ocButton setTitle:@"OC按钮调用JS代码" forState:UIControlStateNormal];
        [self.ocButton setBackgroundColor:[UIColor redColor]];
        [self.ocButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:self.ocButton];
    - (void)buttonClick:(UIButton *)sender
    {
        NSString *textJS = [NSString stringWithFormat:@"OCcallJSClick('%@')",@"我是参数"];
        [self.jsContext evaluateScript:textJS];
    }
    

    WKWebView

    再看新家伙
    头文件倒入,并遵循三个协议

    #import <WebKit/WebKit.h>
    
    @interface WKWebViewDemoViewController ()<WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler>
    

    JS调用OC 并传参数给OC使用

    这里在创建WKWebView中,凡是js调用oc的,需要在创建WKWebView的时候注册一下这个方法

     //创建webview
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        WKUserContentController *userController = [[WKUserContentController alloc] init];
        config.preferences.javaScriptEnabled = YES;
        config.userContentController = userController;
        [userController addScriptMessageHandler:self name:@"JScallOCClick"];
        
        WKWebView *web = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2) configuration:config];
        
    

    在vue中不能再简单的写方法去响应了,应该改成

    //注意,如果是无参  括号内写null,不能写‘’ 也不能什么都不写 这个被坑了一天。。。
    window.webkit.messageHandlers.JScallOCClick.postMessage(b);
    

    同样在代理中响应js的事件

    #pragma mark - 处理与js交互回调
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
    {
        //message中包含了js中所有的信息
        //有两个重要的属性,一个是name,进行区分判断具体响应某个方法
        //body中就是js传过来的参数
        if ([message.name isEqualToString:@"JScallOCClick"]) {
            NSLog(@"%@",message.body);
            [self jsCallOC:message.body];
        }
    }
    
    

    OC调用JS 并传参数给JS使用

    - (void)buttonClick:(UIButton *)sender
    {
        NSString *param = @"我是原生的数据";
        NSString * jsStr  =[NSString stringWithFormat:@"OCcallJSClick('%@')",param];
        [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            NSLog(@"--------error %@",error);
            //此处可以打印error.
            NSLog(@"--------result %@",result);
        }];
    }
    

    注意 WKWebView加载的web中如果有弹窗,需要额外写一个代理处理一下弹窗,不然不会弹出

    #pragma mark - WKUIDelegate
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            completionHandler();
        }]];
        
        [self presentViewController:alert animated:YES completion:nil];
    }
    

    以上简单清晰的描述完了两个框架与VUE的交互,简单如此,但值得整理一下。

    end:如果
    看完这篇
    web和原生总是没有响应

    别着急
    盖上电脑
    然后
    砸了吧 ~ 😆

    相关文章

      网友评论

        本文标题:iOS原生与Vue的方法交互

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