前言
白屏問題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 頁面。
總結
以上是我遇到和整理的白屏問題以及參考解決方案,但願對你們有所幫助,若有疑問歡迎留言交流。
參考文獻