WKWebView 白屏問題,WKWebView request body丟失問題
1,WKWebView 白屏問題
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,從而出現白屏現象。
解決方案:
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
當 WKWebView 總體記憶體佔用過大,頁面即將白屏的時候,系統會呼叫上面的回撥函式代理方法,我們在該函式裡執行[webView reload](這個時候 webView.URL 取值尚不為 nil)解決白屏問題。在一些高記憶體消耗的頁面可能會頻繁重新整理當前頁面,H5側也要做相應的適配操作。
2、WKWebView loadRequest 問題
WKWebView 通過loadrequest方法載入Post請求會丟失請求體(body)中的內容,進而導致伺服器拿不到body中的內容的問題的發生。這個問題的產生主要是因為WKWebView的網路請求的程序與APP不是同一個程序,所以網路請求的過程是這樣的:
由APP所在的程序發起request,然後通過IPC通訊(程序間通訊)將請求的相關資訊(請求頭、請求行、請求體等)傳遞給webkit網路線程序接收包裝,進行資料的HTTP請求,最終再進行IPC的通訊回傳給APP所在的程序的。這裡如果發起的request請求是post請求的話,由於要進行IPC資料傳遞,傳遞的請求體body中根據系統排程,將其捨棄,最終在WKWebView網路程序接受的時候請求體body中的內容變成了空,導致此種情況下的伺服器獲取不到請求體,導致問題的產生。
解決問題:
1.將網路請求交由Js發起,繞開系統WKWebView的網路的程序請求達到正常請求的目的
2.改變POST請求的方法為GET方法(有風險,不一定伺服器會接受GET方法)
3.將Post請求的請求body內容放入請求的Header中,並通過URLProtocol攔截自定義協議,在攔截中通過NSConnection進行重新請求(重新包裝請求body),然後通過回撥Client客戶端來傳遞資料內容
3,WKWebView 頁面樣式問題
在 WKWebView 適配過程中,發現部分H5頁面元素位置向下偏移或被拉伸變形,追蹤後發現主要是H5頁面高度值異常導致:
解決方案:
調整WKWebView佈局方式,避免調整webView.scrollView.contentInset。實際上,即便在 UIWebView 上也不建議直接調整webView.scrollView.contentInset的值,這確實會帶來一些奇怪的問題。如果某些特殊情況下非得調整 contentInset 不可的話,可以通過下面方式讓H5頁面恢復正常顯示:
/**設定contentInset值後通過調整webView.frame讓頁面恢復正常顯示 *參考:http://km.oa.com/articles/show/277372 */ 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,視訊自動播放
WKWebView 需要通過WKWebViewConfiguration.mediaPlaybackRequiresUserAction設定是否允許自動播放,但一定要在 WKWebView 初始化之前設定,在 WKWebView 初始化之後設定無效。