WKWevView有哪些优劣势?
- 更低的内存占用,内存占用是UIWebView的1/4~1/3
- 更快的加载速度
- 更细致的拆分了UIWebViewDelegate中的方法
- 自带进度条
- 可以和js直接互调函数,不比引入WebViewJavascriptBridge等第三方库
- 不自动注入cookie,需要自己注入
在使用WKWebView过程中遇到的坑以及解决方法
1、白屏问题
首先我们要知道产生白屏的原因:WKWebView之所以有更低的内存占用,是因为它是一个多进程组件,Network Loading 以及 UI Rendering 在其它进程中执行(也就是说使用WKWebView总的内存占用不一定比UIWebView少,只是App Process Memory会减少)。在UIWebView上,当内存占用过大,当前APP会crash,而使用WKWebView,WebContent Process会crash,这个时候就产生了白屏。
解决方案:
A、借助WKNavigtionDelegate
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
当WKWebView总体内存占用过大,页面即将白屏时,回调用上面的函数,我们可以在该函数里执行[webView reload]解决白屏问题。
B、检测 webView.title 是否为空
不是所有白屏都会调用上面的函数,比如在h5上present相机,拍照完毕后返回,由于拍照过程消耗了大量内存,可能导致WebContent Process 被系统挂起,但是上面的函数却没有调用。此时可以在 viewWillAppear 的时候检测 webView.title 是否为空来 reload 页面。
2、Cookie问题
WKWebView会将cookie延迟存储进NSHTTPCookieStorage,但是WKWebView发起的请求不会自动带上NSHTTPCookieStorage中的cookie。
解决方案:
a、WKWebView loadRequest 前,在 request header 中设置 Cookie, 解决首个请求 Cookie 带不上的问题;
WKWebView * webView = [WKWebView new];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://h5.qzone.qq.com/mqzone/index"]];
[request addValue:@"skey=skeyValue" forHTTPHeaderField:@"Cookie"];
[webView loadRequest:request];
b、通过 document.cookie 设置 Cookie 解决后续页面(同域)Ajax、iframe 请求的 Cookie 问题;
WKUserContentController* userContentController = [WKUserContentController new];
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: @"document.cookie = 'skey=skeyValue';" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
3、WKWebView 页面样式问题
在 WKWebView 适配过程中,我们发现部分H5页面元素位置向下偏移或被拉伸变形,追踪后发现主要是H5页面高度值异常导致:
webView一般是从(0,0)开始布局,为了适配特殊导航栏需求(透明、下拉刷新、全屏)调整 webView.scrollView.contentInset。对 contentInset 的调整会反馈到 webView.scrollView.contentSize.height 的变化上,比如设置 webView.scrollView.contentInset.top = a,那么contentSize.height的值会增加a,导致H5页面长度增加,页面元素位置向下偏移;
解决方案:
尽量避免调整 contentInset,如果在某些情况下非得调整 contentInset,那么用如下方式使h5恢复正常显示:
webView.scrollView.contentInset = UIEdgeInsetsMake(a, 0, 0, 0);
webView.frame = CGRectMake(webView.frame.origin.x, webView.frame.origin.y, webView.frame.size.width, webView.frame.size.height - a);
4、其他问题
4.1、视频自动播放
WKWebView 需要通过WKWebViewConfiguration.mediaPlaybackRequiresUserAction设置是否允许自动播放,但一定要在 WKWebView 初始化之前设置,在 WKWebView 初始化之后设置无效
4.2、goBack API问题
WKWebView 上调用 -[WKWebView goBack], 回退到上一个页面后不会触发window.onload()函数、不会执行JS。
5、总结
虽然WKWebView有些坑,但是相对 UIWebView 在内存消耗、稳定性方面还是有很大的优势。