在iOS中往往需要跟JS交互的需求,比如某些营销活动之类的,比如抢红包等等
前端的优势在于快速,便捷,样式灵活,这直接关乎产品的市场表现,怎样将其与本地app结合,一直是很多大厂尝试的事,甚至会给所有的开发都带来一场革命,对,我说的就是F8上的ReactNative
不过,现实情况是框架还不完善,体验稳定性都问题,眼下还没有大量的推广,何况apple真的会开放iOS这么大块饼吗?我看未必
我们能做的就是尽量在当下,完成简单的跟web的互调而已,而现实是这点儿也将将够用
本篇不聊原理不谈愿景,只介绍一款优秀的第三方框架和笔者自己使用过程中的一点儿心得
- WebViewJavascriptBridge
这是一款老牌的框架,从11年就有了到现在已经快5年了,一直更新到现在,在github有5K+的star
借助代码看看其使用:
在使用时仅仅自然需要webView,在iOS8之前都是普通的webView,iOS8之后还有一个WKWebView
这里给VC绑定一个webView,like this:
添加属性:1
2@property (nonatomic, strong) UIWebView *webView;
@property (nonatomic, strong) WebViewJavascriptBridge *bridge;
然后在viewDidLoad
方法中:
1 |
|
同时还创建了一个本地的btn
这个框架认定JS和OC之间有两种层次的交互需求:发消息
和传东西
2种,一种仅仅只是为了通信,另一种更重量的使用是相互调方法
想想也是,很多时候并不需要一定要告诉我要怎样操作,仅仅是传递个我一个值就可以了,而有的时候最好能直接调用某一边的方法,其实稍后你就会发现其实两种都是一样的
通信
可以理解为仅仅就是为了传值,使用灵活简便
JS 给 OC 传值
1
2
3
4
5
6
7
8
9
10
11
12
13
14// OC中初始化
self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@" data: %@", data);
responseCallback(@"back");
}];
---------------------
// JS中
bridge.send(data, function(responseData) {
log('[[JS中]] got response', responseData)
})这样就完成了,如图:
OC 给 JS 传值
还记得我们的那个btn吗,更刚才的正好相反:在btn方法中添加OC,而在JS中要加上初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// JS中初始化
<!-- OC向JS发消息,JS中的初始化 -->
<!-- 匿名function对应于OC中所发消息 -->
bridge.init(function(message, responseCallback) {
log('JS中(从OC接收的消息)', message)
var data = { '[[JS中]]接收到消息,并回复':'hello , OC' }
log('[[JS中]]回复', data)
responseCallback(data)
})
---------------------
// OC中btn
NSLog(@" -- 发送消息 --");
[self.bridge send:@"TED is goooood!" responseCallback:^(id responseData) {
NSLog(@"what we receve: %@ ", responseData);
}];结果:
调方法
先明确一点,如果JS -> OC, 说明OC中有方法,反之也一样
JS -> OC
比如:1
2
3
4
5
6
7
8
9
10
11
12
13
14// OC中
[self.bridge registerHandler:@"ZXOCHandler" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"[OC中],JS传来的消息:%@", data);
[self sendMessage:nil];
responseCallback(@"[OC中],已收到");
}];
// JS中
<!-- JS调方法,OC中已经的初始化 -->
bridge.callHandler('ZXOCHandler', data, function(response) {
log('[JS中] got response', response)
})OC -> JS
更改OC中Btn点击的方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// JS中初始化方法
<!--注册 ZXJSHandler 方法-->
bridge.registerHandler('ZXJSHandler', function(data, responseCallback) {
log('[JS中],ZXJSHandler be called, withPra: %@', data)
var backData = {'[JS中]':'ZXJSHandler be called'}
responseCallback(backData)
log('[JS中],ZXJSHandler be called, then responding:', backData)
})
---------------------
// OC的btn中调方法
NSLog(@"-- 调用 ZXJSHandler --");
[self.bridge callHandler:@"ZXJSHandler" data:@"[OC中]来自OC的问候" responseCallback:^(id responseData) {
NSLog(@"ZXJSHandler的回复: %@", responseData);
}];
就死这样的酸爽,就是这样的写意,这些足够满足日常需求了
现在回来看,其实所谓的通信传值,不就是调用对方的init方法吗?所以说2种其实是一回事儿
一点儿吭
在博主实际使用开发app的“邀你注册,给你红包”活动功能中,遇到过一个吭。当时同样的前端代码,在android是正常的,而在ios端无论如何都不运行,或者是偶尔正常,找了所有的问题
撕了不少b
都不觉得有问题
最后发现是webView的机制问题,webView打开一个url发生跳转时,跟安卓不同,是异步的,这就意味着如果有一次性的的链接,比如活动中生命周期唯一的优惠码,如果前端框架也是异步的就会发生永远也拿不到唯一的优惠码,显示的错误为已过期的提示,最终跟前端大哥商量他修改了代码,才搞好
所以🙏前端大哥和浩哥等几位的大哥的耐心与帮助,有些问题真不是自己一个人能搞定的