iOS原生与Vue的方法交互

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

我们写好一个vue网页片段

OC调用JS方法
JS调用OC方法

注意:我们如果是在局域网内测试,比如本文,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使用

要实现原生与网页的交互,我们使用苹果自带的框架 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 

@interface WKWebViewDemoViewController ()

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的方法交互)