前言
白屏问题iOS开发中最使人头疼的问题之一。WKWebView随iOS8 推出已有4年了,解决了不少UIWebView的问题,好比内存泄漏、加载速度慢、不太兼容iOS10, iOS11等。Apple Support iOS版本的市场分布状况,绝大部分的设备都是iOS8 以上,iOS开始强制使用HTTPS请求,但还有部分公司的APP支持iOS7和HTTP请求,要遇上时代的步伐啊!html
WKWebView的特色
- 性能高,稳定性好,占用的内存比较小
- 支持JS交互
- 支持HTML5 新特性
- 能够添加进度条(然并卵,很差用,仍是习惯第三方的)
- 支持内建手势
- 听说高达60fps的刷新频率(不卡)
HTTPS的特色
- HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程当中不被窃取、改变,确保数据的完整性。
- HTTPS协议的安全是有范围的,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么做用。
- SSL的专业证书须要购买,功能越强大的证书费用越高。SSL 证书一般须要绑定 固定IP,为服务器增长固定IP会增长必定费用。
- 相同网络环境下,HTTPS协议会使页面的加载时间延长近50%,增长10%到20%的耗电。此外,HTTPS协议还会影响缓存,增长数据开销和功耗。
- HTTPS 链接服务器端资源占用高较高多,相同负载下会增长带宽和服务器投入成本;
在使用的时候仍是有不少坑,这其中就有家常便饭的白屏问题。通过一些调试、google 发现不外乎这几个缘由。网络通畅是前提哈,请用4G或WiFi网络!!!话很少说了,来一块儿看看都有哪些可能的问题。
一. URL网址无效或含有中文字符(入门级错误)
APP内展现URL的来源主要是后端返回或前端拼接,甚至前端hardcode,网址存在不肯定性,多是无效或含有中文字符。大部分浏览器是能打开带有中文字符的网络地址,可是iOS的内嵌网页加加载框架不管是UIWebView仍是WKWebView,都不能打开带有中文字符的网络地址,须要先对地址字符串作UTF8转码。参考代码:
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];复制代码
二. HTTP请求问题
在iOS9 中,系统将原http协议改为了默认https协议,使用 TLS1.2 SSL加密请求数据。
能够经过升级支持HTTPS协议请求,也能够经过设置强制使用HTTP请求。在Info.plist中添加NSAppTransportSecurity类型Dictionary。在NSAppTransportSecurity下添加NSAllowsArbitraryLoads类型Boolean,值设为YES。
部分第三方应用不支持HTTPS,须要在在info.list设置HTTP请求白名单,容许部分请求能够是HTTP。参考代码:
<key>LSApplicationQueriesSchemes</key>
<array>
<!-- 微信 URL Scheme 白名单-->
<string>wechat</string>
<string>weixin</string>
</array>复制代码
三. HTTPS 请求,未实现证书认证代理致使页面不加载的问题
若是是HTTPS 请求,须要在WKWebView 的 WKNavigationDelegate 中的一个代理方法 中实现获取服务器认证的逻辑,最后返回给服务端。 这个问题经常出如今客户端没法得到安全认证的时候(没有证书,或者是自建证书),好比说https://www.apple.com/cn 是默认的苹果中国的地址,可是 https://www.apple.com.cn 也是能够访问的(会自动跳转到 https://www.apple.com/cn ) ,只是在Safari 的安全认证中通不过,咱们须要在代理方法中经过服务端给的验证方式建立一个凭证,而后继续申请访问。好比在Safari 浏览器中第一次访问时就会弹出对话框,点击继续后就能够继续访问。经过实现如下代理便可解决
func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void)
{
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if challenge.previousFailureCount == 0 {
let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
completionHandler(.UseCredential, credential)
} else {
completionHandler(.CancelAuthenticationChallenge, nil)
}
} else {
completionHandler(.CancelAuthenticationChallenge, nil)
}
}复制代码
四. iOS 8.0 - iOS 8.2 偶尔白屏问题
这个是WKWebView 刚推出时的Bug,偶尔会出现白屏,若是想避免这种问题,只能经过版本号判断,小于8.2的系统暂时使用UIWebView。
五. 滚动组件嵌套,未能刷新页面
在UITableView或UICollectionView中嵌套WKWebView引发的,能够试着将UITableView或UICollectionView中替换为UIScrollview 。多是由于页面滚动后没有正常的调用 WKWebView 的 _updateVisibleContentRects 方法刷新须要渲染的内容致使的。
六. 硬件内存不足、进程崩溃
在 UIWebView 上当内存占用太大的时候,App Process 会 crash;而在 WKWebView 上当整体的内存占用比较大的时候,WebContent Process 会 crash,从而出现白屏现象。在 WKWebView 中加载下面的测试连接能够稳定重现白屏现象:
这个时候 WKWebView.URL 会变为 nil, 简单的 reload 刷新操做已经失效,对于一些长驻的H5页面影响比较大。参考解决方案:
一、借助 WKNavigtionDelegate
iOS 9之后 WKNavigtionDelegate 新增了一个回调函数:
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));复制代码
当 WKWebView 整体内存占用过大,页面即将白屏的时候,系统会调用上面的回调函数,咱们在该函数里执行[webView reload](这个时候 webView.URL 取值尚不为 nil)解决白屏问题。在一些高内存消耗的页面可能会频繁刷新当前页面,H5侧也要作相应的适配操做。
二、检测 webView.title 是否为空
并非全部H5页面白屏的时候都会调用上面的回调函数,好比,最近遇到在一个高内存消耗的H5页面上 present 系统相机,拍照完毕后返回原来页面的时候出现白屏现象(拍照过程消耗了大量内存,致使内存紧张,WebContent Process 被系统挂起),但上面的回调函数并无被调用。在WKWebView白屏的时候,另外一种现象是 webView.titile 会被置空, 所以,能够在 viewWillAppear 的时候检测 webView.title 是否为空来 reload 页面。
总结
以上是我遇到和整理的白屏问题以及参考解决方案,但愿对你们有所帮助,若有疑问欢迎留言交流。
参考文献