最近做的项目里面有详情页面,布局很繁重的那种,用的是html写的,然后就有js与oc相互调用的情况.之前还没搞过,经过这些天大致了解了哈整个的一个过程,然后整理了一下代码(oc以及js的),算是做个笔记.
js调用本地代码时WKWebView与UIWebView是不同的. 在WKWebView中只需增加这么一行代码:
[web1.configuration.userContentControlleraddScriptMessageHandler:selfname:@"function_wkwebview"];
然后在代理方法里面就可以收到调用回调
-(void)userContentController:(WKUserContentController)userContentController didReceiveScriptMessage:(WKScriptMessage)message{
NSLog(@"%@ %@",message.name,message.body);
}
有一个问题是:addScriptMessageHandler:self 之后会强引用一个控制器self,导致pop之后控制器不会销毁,因此需要在viewWillAppear中添加,在viewWillDisappear中移除即可解决:
-(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [web1.configuration.userContentController addScriptMessageHandler:self name:@"function_wkwebview"]; }
-(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [web1.configuration.userContentController removeScriptMessageHandlerForName:@"function_wkwebview"]; }
js部分:
function clickme1() { window.webkit.messageHandlers.function_wkwebview.postMessage("来自js的消息wkwebView")
}
接下来是UIwebView调用oc代码:
pragma mark - UIWebViewDelegate
-(void)webViewDidFinishLoad:(UIWebView)webView{
JSContextcontext=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; context[@"function_uiwebview"]=^(){
NSLog(@"%@",[JSContext currentThis]);
};
}
注意在block中要避免引用外部变量,否则还是会引起内存泄漏.
js部分:
function clickme2(){ window["function_uiwebview"].apply("来自js的消息uiwebView") }
另外,oc调用js中的代码更简单: UIwebView的方法是:
NSString* str=[web2 stringByEvaluatingJavaScriptFromString:@"js_function('传给js函数的参数2')"];
WKWebView的方法是:
[web1 evaluate[removed]@"js_function('传给js函数的参数1')" completionHandler:^(id _Nullable result, NSError * _Nullable error) { NSLog(@"%@",result); }];
方法:js_function('传给js函数的参数1')只需要在js中去实现即可.
代码地址: js 与 Native 互相调用