iOS与JS交互的方法主要有四种如下:
1、拦截url(适用于UIWebView和WKWebView)
2、JavaScriptCore(只适用于UIWebView,iOS7+)
3、WKScriptMessageHandler(只适用于WKWebView,iOS8+)
4、WebViewJavascriptBridge(适用于UIWebView和WKWebView,属于第三方框架)
本便主要讲解WKWebView的MessageHandler方式实现交互;因为相比与 UIWebView, WKWebView 存在很多优势,主要是在性能、稳定性方面有很大提升占用内存更少 协议方法及功能都更细致
WKWebView 初始化时,有一个参数叫configuration,它是WKWebViewConfiguration类型的参数,而WKWebViewConfiguration有一个属性叫userContentController,它又是WKUserContentController类型的参数。WKUserContentController对象有一个方法
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
我把这个功能简称为MessageHandler。
1、JS调用OC时,这句代码非常重要
[config.userContentController addScriptMessageHandler:self name:@"callFunciton"];
在创建wkWebView时,需要将被js调用的方法注册进去,oc与js端对应实现
- (void)setWKWebview{
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences = [[WKPreferences alloc] init];
config.preferences.minimumFontSize = 10;
config.preferences.javaScriptEnabled = YES;
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
config.userContentController = [[WKUserContentController alloc] init];
config.processPool = [[WKProcessPool alloc] init];
config.userContentController = [WKUserContentController new];
//在创建wkWebView时,需要将被js调用的方法注册进去,oc与js端对应实现
[config.userContentController addScriptMessageHandler:self name:@"callFunciton"];
WKWebView *wkWebView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:config];
self.wkWebView = wkWebView;
wkWebView.navigationDelegate = self;
wkWebView.UIDelegate = self;
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:self.url];
[wkWebView loadRequest:request];
[self.view addSubview:wkWebView];
}
- addScriptMessageHandler:name:有两个参数,第一个参数是userContentController的代理对象,第二个参数是JS里发送postMessage的对象。
所以要使用MessageHandler功能,就必须要实现WKScriptMessageHandler协议。
2、JS中使用方法:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
//其中<name>,就是上面方法里的第二个参数`name`。
//例如我们调用API的时候第二个参数填@"callFunction",那么在JS里就是:
window.webkit.messageHandlers.callFunction.postMessage(<messageBody>)
//<messageBody>是一个键值对,键是body,值可以有多种类型的参数,body 的类型:Allowed types are NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull
重要的事情说三遍!重要的事情说三遍!重要的事情说三遍!
window.webkit.messageHandlers.AppModel.postMessage(NULL或者其他参数),参数messageBody里面不能为空什么都不写,不然不会走代理方法
3、实现WKScriptMessageHandler代理方法,当js调用callFunction方法时,会回调此代理方法:
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([message.name isEqualToString:@"callFunction"]) {
//调用原生扫码
}
}
4、addScriptMessageHandler很容易引起循环引用,导致控制器无法被释放
- (void)dealloc{
[self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"callFunction"];
}