先放上bug
演示:
可以看到,在
iPhoneX
上,網頁加載中會在白底的webView
底部出現一塊黑邊,這個就很影響用戶體驗和美觀了,如果加載時間長一點,這個效果就會更加明顯。經過測試,發現這個問題不只出現在
iPhone X
及以上機型,其他機型同樣有,只是平時我們網絡很快的話,不去拉就看不到底部的黑邊,實際是存在超過屏幕外的地方那么怎么解決這個問題呢?
解決方案(網上查閱資料得到) :
self.webView.backgroundColor = [UIColor whiteColor];
self.webView.opaque = NO;
好了,如果只是想看這個問題如何解決的話,到這里就可以點左上角或者右上角叉叉關閉了,以下是我對這兩行代碼如何起作用的一些個人分析(扯淡??)。
分析:
為什么這兩行代碼就解決了這個問題呢?是的,一開始我也以為只是iPhone X
類機型才會出現的問題,會想用這樣的代碼去解決:
//非完美解決方案
self.webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
這樣是很方便,只一行代碼,iPhone X
以上機型不會再出現問題,但同時卻也沒有了底部自動縮進的效果,x類型設備滑到最底部的時候,網頁最底部會緊貼著設備最底部,效果不太好,如果想要自動縮進的話就不方便了。
前者是相當于放棄safeArea
自動縮進的功能來實現去黑邊的效果,但是其他非X類機型
上任然存在問題,而后面這個才是真正解決了問題,且不影響contentInsetAdjustmentBehavior
屬性的使用。
那么這兩行代碼是如何解決這個問題的呢?
我們先來看一下剖析圖
從圖中我們發現
UIWebView
的結構是UIWebView
的子視圖是一個UIWebViewScrollView
,然后UIWebViewScrollView
上又有一個UIWebBrowserView
,就是圖中我選中的View
,很明顯黑邊也就是這個東西導致的。
然后我們從opaque
入手,從官方文檔上,我們得到這樣的介紹
This property provides a hint to the drawing system as to how it should treat the view. If set to YES, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance. If set to NO, the drawing system composites the view normally with other content. The default value of this property is YES.
也就是說,如果這個屬性為YES
,這個視圖就表現出這個屬性的字面意思,不透明,并且繪圖系統會進行一些優化來提升性能;如果設置為NO
,繪圖系統將會把它和其他視圖結合在一起,肯定也不會進行性能優化,所以,這里我們把它關閉,實際上需要它透明,然后不用優化性能。emmm...
所以這跟我們實現的效果有什么關聯呢?
好吧,試著去理解一下,是我們這里的webBrowserView
導致的問題,那么就從它下手,這里提到透明,難道是把webBrowserView
變透明了?嗯?但是我們這里設置opaque
為NO
的不是webView
嗎?說著我嘗試了一下。
因為我是用storyboard
做的,webView
默認opaque
為YES
。
總結一下,正好webView
和webBrowserView
的opaque
屬性都為YES
,好,那我們按照解決方案中說的改為NO
試試。
運行起來:
將webView
的opaque
屬性改成NO
后webBrowserView
的opaque
也變成NO
了,是不是父視圖的opaque
屬性改變會導致相應的子視圖的opaque
屬性跟著變化呢?我也去做了一個實驗,結果證明并沒有絕對的關系,大家有興趣可以試試在一個View
上add
另一個view
,然后兩個view
的opaque
設置不同,打斷點,啵出他們的opaque
屬性,會發現沒有絲毫影響。
那這里因為webView
是系統封裝的一個獨特的視圖,它內部可能有什么不為人知的秘密我這里就只能做個猜測了,如果有懂其中原理的大神還望評論區留言,謝謝啦??!
這里至少證明了webBrowserView
的opaque
會隨著webView
的opaque
屬性相應改變。
好,我們執行了第一句webView
的opaque
設置為NO
的代碼,看下效果
整個
webView
加載后變成了網頁默認的背景顏色,看下剖析圖:
webBrowserView
和webView
的背景顏色變成一樣了,我們改變一下webView
的顏色來證明這個結論:可以看到,將webView
背景顏色設為綠色后,webBrowserView
的背景也變為綠色了。
OK,那么第二句webView.backgroundColor = [UIColor whiteColor]
也可以解釋了,webView
的opaque
設置為NO
后,webBrowser
就沒有了黑邊,并且顏色跟webView
的背景顏色一樣,之所以要寫成白色,可能大多數需求都是白色吧,所以這里又獲得一個技能,想要設置成啥顏色直接改變webView
的背景顏色就可以了,不一定是白色,按照需求來就可以了。
總結:
當webView
的opaque
屬性為YES
時,webBrowserView
的opaque
屬性也為YES
,這個時候,webBrowserView
不透明,且繪畫系統會對它進行優化,可能認為是直接渲染成白色比較省性能吧,也就是性能優化的結果,而底部的黑邊就是加載網頁的內部控件所留下的效果了(關于webBrowserView
內部控件,就觸及到我的盲區了,如果有懂這其中原理的請不吝賜教),總之也是跟性能優化相關;
而將webView
的opaque
屬性設置為NO
時,webBrowserView
也會相應的設置opaque
為NO
(沒有為什么,系統封裝的控件),這個時候繪畫系統就認為webBrowserView
是透明的,卻是直接將webBrowserView
的顏色設置為webView
的顏色,可能是因為webBrowserView
要加載并顯示網頁的內容,不能設置成透明的原因吧,所以并沒有讓它透明,而是做了一個類似透明的效果,也就是將背后視圖的顏色設置為自己的顏色(哈哈,你懂得,猜測)。