WKWebView的介绍

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WKWebView的介绍相关的知识,希望对你有一定的参考价值。

参考技术A WKWebView 是现代 WebKit API 在 ios 8 和 OS X Yosemite 应用中的核心部分。它代替了 UIKit 中的 UIWebView 和 AppKit 中的 WebView,提供了统一的跨双平台 API。

自诩拥有 60fps 滚动刷新率、内置手势、高效的 app 和 web 信息交换通道、和 Safari 相同的 javascript 引擎,WKWebView 毫无疑问地成为了 WWDC 2014 上的最亮点。

WKWebview提供了API实现js交互 不需要借助JavaScriptCore或者webJavaScriptBridge。使用WKUserContentController实现js native交互。简单的说就是先注册约定好的方法,然后再调用。

UIWebView & UIWebViewDelegate 这个两个东西是如何在 WKWebKit 中被重构成 14 个类 3 个协议的呢。

1.WKBackForwardList: 之前访问过的 web 页面的列表,可以通过后退和前进动作来访问到。

    WKBackForwardListItem: webview 中后退列表里的某一个网页。

2.WKFrameInfo: 包含一个网页的布局信息。

3.WKNavigation: 包含一个网页的加载进度信息。

    WKNavigationAction: 包含可能让网页导航变化的信息,用于判断是否做出导航变化。

    WKNavigationResponse: 包含可能让网页导航变化的返回内容信息,用于判断是否做出导航变化。

4.WKPreferences: 概括一个 webview 的偏好设置。

5.WKProcessPool: 表示一个 web 内容加载池。

6.WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法。

    WKScriptMessage: 包含网页发出的信息。

    WKUserScript: 表示可以被网页接受的用户脚本。

        WKWebViewConfiguration: 初始化 webview 的设置。

7.WKWindowFeatures: 指定加载新网页时的窗口属性。

1.WKNavigationDelegate: 提供了追踪主窗口网页加载过程和判断主窗口和子窗口是否进行页面加载新页面的相关方法。

2.WKScriptMessageHandler: 提供从网页中收消息的回调方法。

3.WKUIDelegate: 提供用原生控件显示网页的方法回调

WKWebView 继承了 UIWebView 大部分的接口,这让 app 来继承 WKWebKit 也简单了许多(同时随着更新 iOS 8 的越来越多这也成为了某种必需)。

有兴趣的同学可以看一下这两个类的 API 区别:

相对于 UIWebView 最大的提升就是数据在可以 app 和 web 内容之间传递。

WKUserScript 允许在正文加载之前或之后注入到页面中。这个强大的功能允许在页面中以安全且唯一的方式操作网页内容。

一个简单的例子如下,用户改变背景的用户脚本被插入到网页中:

WKUserScript 对象可以以 JavaScript 源码形式初始化,初始化时还可以传入是在加载之前还是结束时注入,以及脚本影响的是这个布局还是仅主要布局。于是用户脚本被加入到 WKUserContentController 中,并且以 WKWebViewConfiguration 属性传入到 WKWebView 的初始化过程中。

这个样例可以简单扩展为更为高级的页面修改方法,例如去除广告、隐藏评论等,更复杂的样例见此: 让所有出现的”the cloud”变为”my butt” 。

就想在 Safari 审查元素 功能中的 console.log 能在调试终端打印信息一样,网页中的信息也可以通过调用这个函数被传到 app 里:

window.webkit.messageHandlers.NAME.postMessage()

这个 API 真正神奇的地方在于 JavaScript 对象可以_自动转换_为 Objective-C 或 Swift 对象。

Handler 的名字可以通过 WKScriptMessageHandler 协议中的 addScriptMessageHandler() 接口函数设置:

于是当通知进入 app 的时候,比如说在页面中创建一个新对象,相关信息就可以这样传递:

添加用户脚本来对 web 事件监听并用 Message Handler 将信息传回 app。

同样的方法也可以用来收集页面信息用于 app 的页面展示或数据分析。

例如,如果某人要针对 NSHipster.com 做一个特别的浏览器,就可以加一个能够呼出相似文章列表的按钮:

WKWebView使用

WKWebView比之之前使用的UIWebView更加具有优势,UIWebView更加的笨重,UIWebView占用更多的内存,且内存的峰值更加的夸张,WKWebView加载的速度也更快,而且其更多的支持HTML5的特性,官方宣称的高达60fps的公洞刷新率以及内置的手势。

以下是一些WKWebView的一些使用方法及代理方法

加载链接和UIWebView类似

懒加载方法:

- (WKWebView *)webView {
    if (_webView == nil) {
        // js配置
        WKUserContentController *userContentController = [[WKUserContentController alloc] init];
        [userContentController addScriptMessageHandler:self name:@"webViewLoadStart"];
        [userContentController addScriptMessageHandler:self name:@"webViewLoadFinish"];
        [userContentController addScriptMessageHandler:self name:@"webViewLogout"];
        [userContentController addScriptMessageHandler:self name:@"webViewSuccess"];

        // WKWebView的配置
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        configuration.userContentController = userContentController;
        
        // 显示WKWebView
        _webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
        _webView.UIDelegate = self; // 设置WKUIDelegate代理
        _webView.navigationDelegate = self; // 设置WKNavigationDelegate代理
        [self.view addSubview:_webView];
    }
    return _webView;
}

在其中的

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message方法中主要是收到JS的回执脚本就会运行一次

可以在这个方法里面进行app和js的交互

下面是WKUIDelegate一些代理的方法,可以用于输入框,弹出窗的使用

和UIWebView类似的加载,成功,失败的代理方法类似

/// 1 页面开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
/// 2 开始获取到网页内容时返回
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
/// 3 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
/// 4 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;

#pragma mark - WKUIDelegate
#pragma mark alert弹出框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    NSLog(@"%s", __FUNCTION__);
    // 确定按钮
    UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }];
    // alert弹出框
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:alertAction];
    [self presentViewController:alertController animated:YES completion:nil];
}

#pragma mark Confirm选择框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(nonnull NSString *)message initiatedByFrame:(nonnull WKFrameInfo *)frame completionHandler:(nonnull void (^)(BOOL))completionHandler {
    NSLog(@"%s", __FUNCTION__);
    // 按钮
    UIAlertAction *alertActionCancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        // 返回用户选择的信息
        completionHandler(NO);
    }];
    UIAlertAction *alertActionOK = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }];
    // alert弹出框
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:alertActionCancel];
    [alertController addAction:alertActionOK];
    [self presentViewController:alertController animated:YES completion:nil];
}

#pragma mark TextInput输入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(nonnull NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(nonnull WKFrameInfo *)frame completionHandler:(nonnull void (^)(NSString * _Nullable))completionHandler {
    NSLog(@"%s",__FUNCTION__);
    // alert弹出框
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:nil preferredStyle:UIAlertControllerStyleAlert];
    // 输入框
    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = defaultText;
    }];
    // 确定按钮
    [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // 返回用户输入的信息
        UITextField *textField = alertController.textFields.firstObject;
        completionHandler(textField.text);
    }]];
    // 显示
    [self presentViewController:alertController animated:YES completion:nil];
}

以上是关于WKWebView的介绍的主要内容,如果未能解决你的问题,请参考以下文章

使用WKWebView替换UIWebView

WKWebView强大的新特性

WKWebView 设置自定义UserAgent正确姿势

WKWebView 设置自定义UserAgent正确姿势

iOS开发漫话WKWebView之给H5网页图片添加点击事件以实现原生图片预览

WKWebView:表单未在 WKWebView (Swift) 中提交