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 初始化之后設置無效。