首先向大家推荐一篇文章关于iOS与js交互知识点的总结,个人认为有助于大家记忆和理解,感谢作者的整理。
https://github.com/Haley-Wong/JS_OC
关于OC与JS交互方法,我主要使用的是WKWebview,所以js调用oc方法并传值,oc调用js方法并传值,我使用的是MessageHandler。JS_OC_MessageHandler是利用WKWebView提供的新的API实现的JS调用原生OC,更简洁和方便。
一、js调用oc方法:
首先在viewdidload里,配置WKUserContentController和配置WKWebView,代码如下:
//js调用iOS方法配置
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
configuration.preferences=[[WKPreferences alloc]init];
configuration.preferences.javaScriptEnabled=YES;
configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES;
//wkwebview配置
wkwebview =[[WKWebView alloc]initWithFrame:CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height-20) configuration:configuration];
wkwebview.scrollView.bounces=NO;
wkwebview.navigationDelegate=self;
wkwebview.UIDelegate = self;
wkwebview.backgroundColor = [UIColor clearColor];
wkwebview.opaque = NO;
wkwebview.scrollView.scrollEnabled=NO;
[self.view addSubview:wkwebview];
其次,在viewWillAppear里添加ScriptMessageHandler,在viewWillDisappear移除ScriptMessageHandler,代码如下:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[wkwebview.configuration.userContentController addScriptMessageHandler:self name:@"backToIOS"];//h5模块首页返回到导航的返回按钮
[wkwebview.configuration.userContentController addScriptMessageHandler:self name:@"addCollect"];//添加到收藏夹
[wkwebview.configuration.userContentController addScriptMessageHandler:self name:@"cancelCollect"];//取消收藏
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[wkwebview.configuration.userContentController removeScriptMessageHandlerForName:@"backToIOS"];//h5模块首页返回到导航的返回按钮
[wkwebview.configuration.userContentController removeScriptMessageHandlerForName:@"addCollect"];//添加到收藏夹
[wkwebview.configuration.userContentController removeScriptMessageHandlerForName:@"cancelCollect"];//取消收藏
}
最后,在代理方法里:
#pragma mark - WKScriptMessageHandler h5交互(js调iOS方法)
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"方法名:%@", message.name);
NSLog(@"参数:%@", message.body);
if ([message.name isEqualToString:@"backToIOS"]) {
//h5模块首页返回到导航的返回按钮
[self backToLast];
}
if ([message.name isEqualToString:@"addCollect"]) {
//添加到收藏夹
[self requestForAddCollect];//调用添加收藏接口
}
if ([message.name isEqualToString:@"cancelCollect"]) {
//取消收藏
[self requestForCancelCollect];//调用取消收藏接口
}
}
二、oc给js传值:
[wkwebview evaluateJavaScript:@"collectResult('收藏成功')" completionHandler:nil];
三、html相关代码:
js调用oc方法:其中包含两个方法,返回和收藏,一个传type一个不传。
function goBack(){
try{window.webkit.messageHandlers.backToIOS.postMessage(null);}catch (e){}
}
function _addFavorite(){
var html = document.getElementById('favorite').innerHTML;
if(html == '加入收藏'){
try{window.webkit.messageHandlers.addCollect.postMessage({type:'1'});}catch (e){}
}else{
try{window.webkit.messageHandlers.cancelCollect.postMessage({type:'0'}); }catch (e){}
}
}
oc调用js方法,给js传值:
<script>
var VM = new Vue({
el: '#app',
data: function () {
return {
favorite:'加入收藏'
};
},
mounted() {
window.collectResult = this.collectResult
},
methods: {
collectResult:function(res) {
this.$toast({
message: res,
position: 'middle',
duration: 5000
});
if(res.indexOf("收藏成功")>-1){
this.favorite ='取消收藏';
}else{
this.favorite ='加入收藏';
}
},
}
})
</script>
四、关于oc给js传值,遇到的大坑:
当我调用collectResult方法,给其传一个字符串时,遇到传值方法报error:
Error Domain=WKErrorDomain Code=4 "发生 JavaScript 异常" UserInfo={WKJavaScriptExceptionLineNumber=1, WKJavaScriptExceptionMessage=ReferenceError: Can't find variable: collectResult
然后js那边也没有收到我的值,我这边打印result是null。
原因是由于h5同事是用vue2.0写的,vue中需要将方法挂载到全局中,正确的前端写法是在mounted方法里面加上window.collectResult = this.collectResult。
即在代码里加上:
mounted() {
window.payResult = this.payResult
},