WKWebView是苹果在iOS8推出的,用来替换UIWebView,相比UIWebView,WKWebView速度更快,占用内存更少。
Objective-C与JS交互的办法大致有:
1、UIWebView拦截URL和WKWebView拦截URL。
2、UIWebView调用JavaScriptCore,JavaScriptCore是iOS7新添加的框架。
3、WKWebView使用WKScriptMessageHandler和Objective-C交互。
4、UIWebView调用WebViewJavascriptBridge和WKWebView调用WebViewJavascriptBridge。
5、Cordova
因为WKWebView是以后主流的选择,所以了解了下WKWebView的特性WKScriptMessageHandler来实现交互。
#pragma mark
#pragma mark - Configuration
- (void)initWKWebView {
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = [WKUserContentController new];
self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
[configuration.userContentController addScriptMessageHandler:self name:@"ShowMessageFromWKWebView"];
NSString *webViewURLStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];
NSURL *fileURL = [NSURL fileURLWithPath:webViewURLStr];
[self.wkWebView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
self.wkWebView.UIDelegate = self;
[self.view addSubview:self.wkWebView];
}
这是初始化WKWebView的代码,其中WKUserContentController有一个方法:
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
这是Objective-C方面实现和JS交互的关键方法,需要实现WKScriptMessageHandler协议。
再来看JS方面的使用方法:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
这里的<name>,就是addScriptMessageHandler方法里的第二个参数name。
<messageBody>可以有很多种类型的参数,在WKScriptMessageHandler协议中,message是WKScriptMessage类型,有一个属性body。
创建了WKWebView后我们实现其协议WKScriptMessageHandler和WKUIDelegate,WKScriptMessageHandler是我们要处理JS里点击的事件,WKUIDelegate是我们在JS弹出了alert。
#pragma mark
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"body:%@", message.body);
if ([message.name isEqualToString:@"ShowMessageFromWKWebView"]) {
[self showMessageWithParams:message.body];
}
}
#pragma mark
#pragma mark - WKUIDelegate
/*
*响应JS里的alert提醒
*/
/*
function asyncAlert(alertStr) {
setTimeout(function() {
alert(alertStr);
}, 1);
}
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}]];
[self presentViewController:alertController animated:YES completion:nil];
}
WKScriptMessage里有两个属性name、body。name是我们自己取的名字,可以用来区分不同的方法,而body里是JS传给Objective-C的参数。
#pragma mark
#pragma mark - Show Message
- (void)showMessageWithParams:(NSDictionary *)dict {
if (![dict isKindOfClass:[NSDictionary class]]) {
return;
}
NSString *messageStr = [dict objectForKey:@"message"];
NSString *titleStr = [dict objectForKey:@"title"];
NSLog(@"title:%@", titleStr);
NSLog(@"messageStr:%@", messageStr);
// do it
// 将结果返回给js
NSString *returnJSStr = [NSString stringWithFormat:@"showMessageFromWKWebViewResult('%@')", @"message传到OC成功,message传到OC成功,message传到OC成功,message传到OC成功,message传到OC成功,message传到OC成功"];
[self.wkWebView evaluateJavaScript:returnJSStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@,%@", result, error);
}];
}
文章有借鉴简书Haley_Wong之处。