WKWebView和UIWebView
UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView。通过简单的测试即可发现UIWebView占用过多内存,且内存峰值更是夸张。WKWebView网页加载速度也有提升,但是并不像内存那样提升那么多。下面列举一些其它的优势:
- 更多的支持HTML5的特性
- 官方宣称的高达60fps的滚动刷新率以及内置手势
- Safari相同的JavaScript引擎
- 将UIWebViewDelegate与UIWebView拆分成了14类与3个协议(官方文档说明)
- 另外用的比较多的,增加加载进度属性:estimatedProgress
UIWebView
OC调用JS
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:
JS调用OC
让Native 代码拦截, - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest:)request navigationType:(UIWebViewNavigationType)navigationType
方案中进行拦截处理。
WKWebView
OC调用JS
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^_Nullable)(_Nullable id,NSError * _Nullable error))completionHandler;
WKWebView 本身提供一个方法进行处理JS代码
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
JS调用OC
在JS端的操作
window.webkit.messageHandlers.<方法名>.postMessage(<数据>)
在OC中的处理方法
- (void)addScriptMessageHandler:(id<WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
具体如下
//设置addScriptMessageHandler与name.并且设置<WKScriptMessageHandler>协议与协议方法
[[_webView configuration].userContentController addScriptMessageHandler:self name:@"方法名"];
//WKScriptMessageHandler协议方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
//code
}
如果你在self的dealloc打个断点,会发现self没有释放,这显示是不行的。
思路是另外创建一个代理对象,然后通过代理对象回调指定的self。
WKWebView 坑
WKWebView 白屏问题
WKWevView Cookie 问题
WKWebView NSURLProtocol问题
- WKWebView 在独立于app进程之外的进程中执行网络请求,请求数据不经过主进程,因此,在WKWebView上直接使用NSURLProtocol无法拦截请求。
- post 请求body 数据被清空(encode的时候HTTPBody和HTTPBodyStream 这两个字段被丢弃了)
由于 WKWebView 在独立进程里执行网络请求。一旦注册 http(s) scheme 后,网络请求将从 Network Process 发送到 App Process,这样 NSURLProtocol 才能拦截网络请求。在 webkit2 的设计里使用 MessageQueue 进行进程之间的通信,Network Process 会将请求 encode 成一个 Message,然后通过 IPC 发送给 App Process。出于性能的原因,encode 的时候 HTTPBody 和 HTTPBodyStream 这两个字段被丢弃掉了(参考苹果源码:
https://github.com/WebKit/webkit/blob/fe39539b83d28751e86077b173abd5b7872ce3f9/Source/WebKit2/Shared/mac/WebCoreArgumentCodersMac.mm#L61-L88 及bug report: <WKWebView does not fully support custom NSURLProtocol>)。
- 对ATS支持不足
测试发现一旦打开ATS开关:Allow Arbitrary Loads 选项设置为NO,同时通过 registerSchemeForCustomProtocol 注册了 http(s) scheme,WKWebView 发起的所有 http 网络请求将被阻塞(即便将Allow Arbitrary Loads in Web Content 选项设置为YES);
WKWebView 可以注册 customScheme, 比如 dynamic://, 因此希望使用离线功能又不使用 post 方式的请求可以通过 customScheme 发起请求,比如 dynamic://http://www.dynamicalbumlocalimage.com/,然后在 app 进程 NSURLProtocol 拦截这个请求并加载离线数据。不足:使用 post 方式的请求该方案依然不适用,同时需要 H5 侧修改请求 scheme 以及 CSP 规则
WKWebView loadRequest 问题
- 在WKWebView 上通过loadRequ发起的post请求body数据被丢失
//同样是由于进程间通信性能问题,HTTPBody字段被丢弃
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[@"bodyData" dataUsingEncoding:NSUTF8StringEncoding]];
[wkwebview loadRequest: request]
WKWebView 页面样式问题
WKWebView 截屏问题
WkWebView crash 问题
WKWebView和UIWebView 的区别
WKWebView 更快(占用内存可能只有 UIWebView 的1/3~1/4),没有缓存,更为细致地拆分了 UIWebViewDelegate 中的方法。
想要了解更多关于 WKWebView 的特性的,可以自行 Google,这里你可以简单地把它当做是轻量级的 UIWebView
网络优化
WebViewJavascriptBridge
https://tech.meituan.com/WebViewPerf.html
https://zhuanlan.zhihu.com/p/24990222
https://github.com/CheeryLau/WKWebView