WKWebView与JS交互

       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 )scriptMessageHandler name:(NSString *)name;
这是Objective-C方面实现和JS交互的关键方法,需要实现WKScriptMessageHandler协议。

再来看JS方面的使用方法:

window.webkit.messageHandlers..postMessage()
这里的,就是addScriptMessageHandler方法里的第二个参数name。

可以有很多种类型的参数,在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之处。







你可能感兴趣的:(iOS)