1 额外的进程
WKWebView有额外的2个进程,Networking负责网络请求和WebContent负责内容渲染,所以性能较好,且内存占用低。虽然总的占用内存不变,但App占用的内存大幅下降,减小了被强杀的风险,而且额外进程的崩溃不会影响App。
2 与UIWebView的差异
WKWebView和UIWebView的代理方法发生了一些改变,WKWebView的流程更加细化了。例如之前UI结束请求后,会立刻渲染到webView上。而WKWebView则会在渲染到屏幕之前,会回调一个代理方法,代理方法决定是否渲染到屏幕上。这样就可以对请求下来的数据做一次校验,防止数据被更改,或验证视图是否允许被显示到屏幕上。
除此之外,WKWebView相对于UIWebView还多了一些定制化操作。
1,重定向的回调,可以在请求重定向时获取到这次操作。
当WKWebView进程异常退出时,可以通过回调获取。
自定义处理证书。
更深层的UI定制操作,将alert等UI操作交给原生层面处理,而UI方案UIAlertView是直接由webView显示的。
3 遇到的坑
坑1 打开新网页
不支持_blank,_blank用来打开一个新的网页,但WKWebView下却点击无反应。需要进行特殊处理,
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
坑2 电话
之前在UIWebView上正常的href=“tel:13764567708”,href=“mailto:think@126.com”,现在WKWebView上,无法呼起拨打电话/发邮件,需要在decidePolicyForNavigationAction里面判断URL的scheme(tel、mailto等等),然后用[UIApplication sharedApplication] openURL的方式来拨打电话。不止是电话,跳转App Store等也需要在端内特殊处理。
坑3 弹窗
之前在UIWebView下的alert弹窗,在WKWebView下无法显示,需要在runJavaScriptAlertPanelWithMessage里面进行处理,转换为UIAlertController然后进行展示,注意completionHandler在UIAlertController消失时一定要调用,否则crash。之前做的功能会在呼起正文时,dismiss掉所有的UIAlertController,但没料到这个是WKWebView的弹出UIAlertController,没有调用completionHandler而出现了crash。
不仅是alert弹窗,confirm和input类型的都需要实现协议,转化为Native来实现。
坑4 白屏
如果WKWebView加载内存占用过多的页面,会导致WebContent Process进程崩溃,进而页面出现白屏,出现白屏后,可以在
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
进行重新加载当前网页。
如果从其他App回来导致白屏问题,可以在视图将要显示的时候,判断webView.title是否为空。如果为空则重新加载当前网页。
坑5 属性默认值的不同
allowsLinkPreview在UIWebView默认为NO,而在WKWebView中为YES。
优化1
提前初始化WebView,需要时直接加载URL,能节省100ms时间。
优化2 设置Cookie
根据版本选择不同的方案。
在iOS 11 及以上,因为有了WKHTTPCookieStore,因此最简单,直接用这个类同步登录信息的cookie,来解决WKWebView的cookie的问题。用NSHTTPCookieStorage同步登录信息的cookie处理其他的情况。
在iOS11以下使用下面的方案:
1、请求时在reqeust的header中设置cookie,解决首个请求 Cookie 带不上的问题
2、通过WKUserScript进行注入JS注入,设置cookie,解决后续页面(同域)Ajax、iframe 请求的 Cookie 问题
3,在decidePolicyForNavigationAction,新建一个cookieWebView,在这个cookieWebView中,注入设置cookie的JS,然后加载一个相同域名的空html,同时这个cookieWebView和展示的WebView用一个ProcessPool。这样展示的WebView就有了这里设置的cookie。
4,用NSHTTPCookieStorage同步登录信息的cookie处理其他的情况。