iOS原生与Vue的方法交互

最近公司很多项目涉及到在原生中嵌入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和原生总是没有响应

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容