WKWebView是ios 8 出来的,是为了解决UIWebView卡慢,占用内存过大的问题。

在以往时候,如果用UIWebView加载加载网页的时候,卡慢现象会很严重,有时候往往会卡到一个页面无法动弹,空白屏时间过长,基本上没有什么体验可言;

WebKit中的WKWebView控件的新特性和使用方法,较好的解决了卡、慢、占用内存过大的问题。而且支持了更多HTML5的特性,还有JS库的加载和使用,功能比UIWebView强大了很多。

一、概述

如上图所示,WebKit框架中最核心的类应该属于WKWebView了,这个类专门用来渲染网页视图,其他类和协议都将基于它和服务于它。
WKWebView:网页的渲染与展示,通过WKWebViewConfiguration可以进行自定义配置。
WKWebViewConfiguration:这个类专门用来配置WKWebView。
WKPreference:这个类用来进行相关webView设置。
WKProcessPool:这个类用来配置进程池,与网页视图的资源共享有关。
WKUserContentController:这个类主要用来做native与JavaScript的交互管理。
WKUserScript:用于进行JavaScript注入。
WKScriptMessageHandler:这个类专门用来处理JavaScript调用native的方法。
WKNavigationDelegate:网页跳转间的导航管理协议,这个协议可以监听网页的活动。
WKNavigationAction:网页某个活动的示例化对象。
WKUIDelegate:用于交互处理JavaScript中的一些弹出框。
WKBackForwardList:堆栈管理的网页列表。
WKBackForwardListItem:每个网页节点对象。

二、相关的属性

/// webView的自定义配置
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration; /// 导航代理
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate; /// UI代理
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate; /// 访问过网页历史列表
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList; /// 自定义初始化webView
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; /// url加载webView视图
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request; /// 文件加载webView视图
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0)); /// HTMLString字符串加载webView视图
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL; /// NSData数据加载webView视图
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL API_AVAILABLE(macosx(10.11), ios(9.0)); /// 返回上一个网页节点
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; /// 网页的标题
@property (nullable, nonatomic, readonly, copy) NSString *title; /// 网页的URL地址
@property (nullable, nonatomic, readonly, copy) NSURL *URL; /// 网页是否正在加载
@property (nonatomic, readonly, getter=isLoading) BOOL loading; /// 加载的进度 范围为[0, 1]
@property (nonatomic, readonly) double estimatedProgress; /// 网页链接是否安全
@property (nonatomic, readonly) BOOL hasOnlySecureContent; /// 证书服务
@property (nonatomic, readonly, nullable) SecTrustRef serverTrust API_AVAILABLE(macosx(10.12), ios(10.0)); /// 是否可以返回
@property (nonatomic, readonly) BOOL canGoBack; /// 是否可以前进
@property (nonatomic, readonly) BOOL canGoForward; /// 返回到上一个网页
- (nullable WKNavigation *)goBack; /// 前进到下一个网页
- (nullable WKNavigation *)goForward; /// 重新加载
- (nullable WKNavigation *)reload; /// 忽略缓存 重新加载
- (nullable WKNavigation *)reloadFromOrigin; /// 停止加载
- (void)stopLoading; /// 执行JavaScript
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler; /// 是否允许左右滑动,返回-前进操作 默认是NO
@property (nonatomic) BOOL allowsBackForwardNavigationGestures; /// 自定义代理字符串
@property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAILABLE(macosx(10.11), ios(9.0)); /// 在iOS上默认为NO,标识不允许链接预览
@property (nonatomic) BOOL allowsLinkPreview API_AVAILABLE(macosx(10.11), ios(9.0)); /// 滚动视图
@property (nonatomic, readonly, strong) UIScrollView *scrollView; /// 是否支持放大手势,默认为NO
@property (nonatomic) BOOL allowsMagnification; /// 放大因子,默认为1
@property (nonatomic) CGFloat magnification; /// 据设置的缩放因子来缩放页面,并居中显示结果在指定的点
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point; /// 证书列表
@property (nonatomic, readonly, copy) NSArray *certificateChain API_DEPRECATED_WITH_REPLACEMENT("serverTrust", macosx(10.11, 10.12), ios(9.0, 10.0));

三、使用

WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://developer.apple.com/reference/webkit"]]];
[self.view addSubview:webView];

自定义配置
再WKWebView里面注册供JS调用的方法,是通过WKUserContentController类下面的方法:

- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

自定义配置
再WKWebView里面注册供JS调用的方法,是通过WKUserContentController类下面的方法: - (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

实现WKScriptMessageHandler协议方法

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
  // 判断是否是调用原生的
if ([@"NativeMethod" isEqualToString:message.name]) {
   // 判断message的内容,然后做相应的操作
  if ([@"close" isEqualToString:message.body]) {   }
}
}

注意:上面将当前ViewController设置为MessageHandler之后需要在当前ViewController销毁前将其移除,否则会造成内存泄漏。

[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"NativeMethod"];

四、WKNavigationDelegate代理方法

如果实现了代理方法,一定要在decidePolicyForNavigationAction和decidePolicyForNavigationResponse方法中的回调设置允许跳转。

typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) {
WKNavigationActionPolicyCancel, // 取消跳转
WKNavigationActionPolicyAllow, // 允许跳转
} API_AVAILABLE(macosx(10.10), ios(8.0));
// 1 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSLog(@"1-------在发送请求之前,决定是否跳转 -->%@",navigationAction.request); decisionHandler(WKNavigationActionPolicyAllow);
} // 2 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"2-------页面开始加载时调用");
} // 3 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
/// 在收到服务器的响应头,根据response相关信息,决定是否跳转。decisionHandler必须调用,来决定是否跳转,参数WKNavigationActionPolicyCancel取消跳转,WKNavigationActionPolicyAllow允许跳转 NSLog(@"3-------在收到响应后,决定是否跳转"); decisionHandler(WKNavigationResponsePolicyAllow);
} // 4 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSLog(@"4-------当内容开始返回时调用");
} // 5 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"5-------页面加载完成之后调用");
} // 6 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation { NSLog(@"6-------页面加载失败时调用");
} // 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"-------接收到服务器跳转请求之后调用");
} // 数据加载发生错误时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"----数据加载发生错误时调用");
} // 需要响应身份验证时调用 同样在block中需要传入用户身份凭证
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
//用户身份信息 NSLog(@"----需要响应身份验证时调用 同样在block中需要传入用户身份凭证"); NSURLCredential *newCred = [NSURLCredential credentialWithUser:@""
password:@""
persistence:NSURLCredentialPersistenceNone];
// 为 challenge 的发送方提供 credential
[[challenge sender] useCredential:newCred forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential,newCred);
} // 进程被终止时调用
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
NSLog(@"----------进程被终止时调用");
}

五、WKUIDelegate代理方法

/**
* web界面中有弹出警告框时调用
*
* @param webView 实现该代理的webview
* @param message 警告框中的内容
* @param completionHandler 警告框消失调用
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(void (^)())completionHandler { NSLog(@"-------web界面中有弹出警告框时调用");
} // 创建新的webView时调用的方法
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures { NSLog(@"-----创建新的webView时调用的方法");
return webView;
} // 关闭webView时调用的方法
- (void)webViewDidClose:(WKWebView *)webView { NSLog(@"----关闭webView时调用的方法");
} // 下面这些方法是交互JavaScript的方法
// JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler { NSLog(@"%@",message);
completionHandler(YES);
}
// JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{ NSLog(@"%@",prompt);
completionHandler(@"");
} // 默认预览元素调用
- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo { NSLog(@"-----默认预览元素调用");
return YES;
} // 返回一个视图控制器将导致视图控制器被显示为一个预览。返回nil将WebKit的默认预览的行为。
- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions { NSLog(@"----返回一个视图控制器将导致视图控制器被显示为一个预览。返回nil将WebKit的默认预览的行为。");
return self;
} // 允许应用程序向它创建的视图控制器弹出
- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController { NSLog(@"----允许应用程序向它创建的视图控制器弹出"); } // 显示一个文件上传面板。completionhandler完成处理程序调用后打开面板已被撤销。通过选择的网址,如果用户选择确定,否则为零。如果不实现此方法,Web视图将表现为如果用户选择了取消按钮。
- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * _Nullable URLs))completionHandler { NSLog(@"----显示一个文件上传面板"); }

附:

官方文档地址:https://developer.apple.com/documentation/webkit?language=objc

美团技术团队WebView性能、体验分析与优化:https://tech.meituan.com/WebViewPerf.html?utm_source=tool.lu

ios开发之--WKWebView的使用的更多相关文章

  1. [iOS开发]WKWebView加载JS

    最近项目要用webView加载js文件,挺同事说WKWebView比UIWebView更加好用,于是我今天就试试,百度一发,自己写了个demo. 先看我写的代码,然后再来看WKWebView跟UIWe ...

  2. ios开发中的小技巧

    在这里总结一些iOS开发中的小技巧,能大大方便我们的开发,持续更新. UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIViewal ...

  3. IOS开发基础知识--碎片47

    1:解决ios静态库中的类别(category)在工程中不能使用 解决方法为:找到 target 的图标,更改其 Other Linker Flags 为: -all_load 或 -force_lo ...

  4. iOS开发笔记7:Text、UI交互细节、两个动画效果等

    Text主要总结UILabel.UITextField.UITextView.UIMenuController以及UIWebView/WKWebView相关的一些问题. UI细节主要总结界面交互开发中 ...

  5. iOS:iOS开发非常全的三方库、插件等等

    iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...

  6. iOS开发之资料收集

    github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自github:https://github ...

  7. iOS开发 非常全的三方库、插件、大牛博客等等

    UI 下拉刷新 EGOTableViewPullRefresh- 最早的下拉刷新控件. SVPullToRefresh- 下拉刷新控件. MJRefresh- 仅需一行代码就可以为UITableVie ...

  8. [iOS 开发] WebViewJavascriptBridge 从原理到实战 · Shannon's Blog

    前言:iOS 开发中,h5 和原生实现通信有多种方式, JSBridge 就是最常用的一种,各 JSBridge 类库的实现原理大同小异,这篇文章主要是针对当前使用最为广泛的 WebViewJavas ...

  9. iOS开发系列--Swift语言

    概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...

随机推荐

  1. PCL学习八叉树

    建立空间索引在点云数据处理中有着广泛的应用,常见的空间索引一般 是自顶而下逐级划分空间的各种空间索引结构,比较有代表性的包括BSP树,KD树,KDB树,R树,四叉树,八叉树等索引结构,而这些结构中,K ...

  2. jq 智能搜索

    案例:http://www.runoob.com/jqueryui/example-autocomplete.html <input  type="text" style=& ...

  3. C# 最全的系统帮助类

    using System;using System.Collections;using System.Collections.Generic;using System.Configuration;us ...

  4. add new row to data.frame/dataframe

    df<-NULL new_row<-data.frame(colA="xxx",colB=123) df<-rbind(df,new_row)

  5. Linux 内核版本,Ubuntu版本的查看

    查看内核版本 1)  cat /proc/version [root@a ~]# cat /proc/version Linux version 2.6.18-194.el5 (mockbuild@x ...

  6. 关于session_cache_expire 的理解

    session_cache_limiter,它是session在客户端的缓存方式,有nocache,private,private_no_expire,publice主这几种. cache是属于浏览器 ...

  7. Lua------------------改善Unity编辑器对Lua文件的支持

    原创 2017年03月10日 18:44:22 标签: Unity / lua / 编辑器 952 当前版本的Unity(截至Unity5.5.x)中TextAsset类不支持后缀为lua的文件,将l ...

  8. JavaScript数据去掉空值

    js数组中过滤掉false, null, 0, "", undefined, and NaN值的方法 对于 false,null,0,undefiend,NaN直接取!得到的都是t ...

  9. VS 调试 无法启动IIS Express Web 服务器(进程不存在)

    拷贝VS2015项目 出现无法启动IIS Express Web 服务器 一.把你们拷贝刀本机的解决方案文件中的隐藏文件夹.vs删除掉 重新生产解决方案就可以启动iis express了.

  10. 机器学习——使用Apriori算法进行关联分析

    从大规模的数据集中寻找隐含关系被称作为关联分析(association analysis)或者关联规则学习(association rule learning). Apriori算法 优点:易编码实现 ...