美文网首页iOS学习笔记iOS程序猿iOS Developer
【iOS】WKWebView和Javascript的互调

【iOS】WKWebView和Javascript的互调

作者: Always_on | 来源:发表于2017-01-14 18:39 被阅读89次

在iOS8以后苹果开始提供新的组件WKWebView,其框架为webkit,框架的推出,有效的用WKWebView替代了UIWebView,WKWebView无论在加载耗时或者内存占用上都要优于UIWebView,在功能上有更完善的交互体系,可以让OC与JS的沟通更加明显易读,根据实际的项目测试,使用WKWebView的内存占用率仅仅是UIWebView的1/3~1/4,这么大的内存占用差距,还是让很多开发者或者公司感兴趣的,其次是对H5的支持和JS的更广泛使用,代理方面也细分的更加明确;
接下来直入正题吧;
使用WKWebView需要导入头文件#import <WebKit/WebKit.h>
WKWebView中调用JS使用的方法是:

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

初始化WKWebView

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    // 设置偏好设置
    config.preferences = [[WKPreferences alloc] init];
    // 默认为0
    config.preferences.minimumFontSize = 0;
    // 默认认为YES
    config.preferences.javaScriptEnabled = YES;
    // iOS上默认为NO,表示不能自动通过窗口打开
    config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
    //UserContentController提供javaScript向webView发送消息的方法
    WKUserContentController *userContent = [[WKUserContentController alloc] init];
    //添加消息处理
    [userContent addScriptMessageHandler:self name:@"firstMethod"];
    [userContent addScriptMessageHandler:self name:@"secondMethod"];
    //将UserContentController设置到配置文件中
    config.userContentController = userContent;
    
    _wkWebview = [[WKWebView alloc]initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-64) configuration:config];
    _wkWebview.UIDelegate = self;
    _wkWebview.navigationDelegate = self;
    [self.view addSubview:_wkWebview];
    [_wkWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.1.101/php/demo1.html"]]];

OC调JS,创建两个按钮,分别无参数调用JS和有参数调用JS:

UIButton *button1 = [[UIButton alloc]initWithFrame:CGRectMake(20, [UIScreen mainScreen].bounds.size.height - 64, 105, 50)];
    button1.layer.cornerRadius = 25;
    button1.layer.masksToBounds = YES;
    [button1 setTitle:@"调JS无参数" forState:UIControlStateNormal];
    button1.backgroundColor = [UIColor grayColor];
    [self.view addSubview:button1];
    [button1 addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
    
    UIButton *button2 = [[UIButton alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - 125, [UIScreen mainScreen].bounds.size.height - 64, 105, 50)];
    button2.layer.cornerRadius = 25;
    button2.layer.masksToBounds = YES;
    [button2 setTitle:@"调JS有参数" forState:UIControlStateNormal];
    button2.backgroundColor = [UIColor grayColor];
    [self.view addSubview:button2];
    [button2 addTarget:self action:@selector(buttonClickWithName) forControlEvents:UIControlEventTouchUpInside];
- (void)buttonClick
{
    [self.wkWebview evaluateJavaScript:@"OC_JS()" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
    }];
}
- (void)buttonClickWithName
{
    [self.wkWebview evaluateJavaScript:@"OC_JSWithName('hanmeimei')" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
    }];
}

html代码,本人前端小白,写的不好大家勿怪:​

<!DOCTYPE html>
<html lang="en">
<head>    
<meta charset="UTF-8">    
    <title>测试测试</title>
</head>
<body bgcolor="#faebd7">
    <p>p标签1</p>
    <p>p标签2</p>
    <button style="width:100px ;height:50px" onclick="firstMethod()">调OC1</button>
    <button style="width:100px ;height:50px" onclick="secondMethod()">调OC2</button>
    <script>
        function OC_JS() {
            alert("wkwebview调用OC不带参数");
        }
        function OC_JSWithName(name) {
            alert("wkwebview调用OC带参数:"+name);
        }
        function firstMethod(){                 
            window.webkit.messageHandlers.firstMethod.postMessage("我要调用firstMethod方法");
        }
        function secondMethod() {                
            window.webkit.messageHandlers.secondMethod.postMessage("我要调用secondMethod方法");
        }
    </script>
</body>
</html>

注意:WKWebView如果有alert需要在OC代码实现如下方法:

#pragma mark - WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];
    
    [alertView addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    
    [alertView addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *_Nonnull action){
        completionHandler();
    }]];
    [self presentViewController:alertView animated:YES completion:nil];
}

常用代理WKNavigationDelegate

#pragma mark - WKNavigationDelegate
//开始加载时调用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
}
//当内容开始返回时调用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{   
}
//页面加载完成之后调用
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{ 
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
{
}

分别点击下面两个按钮调取JS方法;

JS调用OC:

为WKWebView添加消息处理:


Snip20170114_11.png

对应html代码:


Snip20170105_23.png
JS调用OC我们可以根据name和body,进行处理;
//js调用OC我们可以根据name和body,进行处理。
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    NSString *messageName = message.name;
    if ([@"firstMethod" isEqualToString:messageName]) {
        id messageBody = message.body;
        NSLog(@"%@",messageBody);
        //在这里写OC中要执行的方法
    }
    if([@"secondMethod" isEqualToString:messageName]){
        id messageBody = message.body;
        NSLog(@"%@",messageBody);
        //在这里写OC中要执行的方法
    }
}
Snip20170105_26.png

点击调用OC1 OC2,xcode控制台分别打印message.body


Snip20170105_27.png

相关文章

网友评论

    本文标题:【iOS】WKWebView和Javascript的互调

    本文链接:https://www.haomeiwen.com/subject/rmnebttx.html