1、WKWebView 自詡擁有更快的加載速度,更低的內存占用,但實際上 WKWebView 是一個多進程組件,Network Loading 以及 UI Rendering 在其它進程中執行。初次適配 WKWebView 的時候,我們也驚訝於打開 WKWebView 后,App 進程內存消耗反而大幅下降,但是仔細觀察會發現,Other Process 的內存占用會增加。在一些用 webGL 渲染的復雜頁面,使用 WKWebView 總體的內存占用(App Process Memory + Other Process Memory)不見得比 UIWebView 少很多。
在 UIWebView 上當內存占用太大的時候,App Process 會 crash;而在 WKWebView 上當總體的內存占用比較大的時候,WebContent Process 會 crash,從而出現白屏現象。在 WKWebView 中加載下面的測試鏈接可以穩定重現白屏現象:
http://people.mozilla.org/~rnewman/fennec/mem.html
這個時候 WKWebView.URL 會變為 nil, 簡單的 reload 刷新操作已經失效,對於一些長駐的H5頁面影響比較大。
我們最后的解決方案是:
A、借助 WKNavigtionDelegate
iOS 9以后 WKNavigtionDelegate 新增了一個回調函數:
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
當 WKWebView 總體內存占用過大,頁面即將白屏的時候,系統會調用上面的回調函數,我們在該函數里執行[webView reload](這個時候 webView.URL 取值尚不為 nil)解決白屏問題。在一些高內存消耗的頁面可能會頻繁刷新當前頁面,H5側也要做相應的適配操作。
B、檢測 webView.title 是否為空 並不是所有H5頁面白屏的時候都會調用上面的回調函數,比如,最近遇到在一個高內存消耗的H5頁面上 present 系統相機,拍照完畢后返回原來頁面的時候出現白屏現象(拍照過程消耗了大量內存,導致內存緊張,WebContent Process 被系統掛起),但上面的回調函數並沒有被調用。在WKWebView白屏的時候,另一種現象是 webView.titile 會被置空, 因此,可以在 viewWillAppear 的時候檢測 webView.title 是否為空來 reload 頁面。
綜合以上兩種方法可以解決絕大多數的白屏問題。