開(kāi)發(fā)中使用 UIWebView 來(lái)展示html頁(yè)面已經(jīng)是鋪天蓋地了。每每產(chǎn)品來(lái)句這個(gè)頁(yè)面html做, 心中真是輕松加愉快~~~
然而树姨,UIWebView 的坑仔細(xì)想想真是不少。。傻寂。。不知道是不是因?yàn)榭犹嘈訟pple干脆做了個(gè)WebKit疾掰,然后從iOS8開(kāi)始,可以使用WKWebView徐紧。記得之前看的C預(yù)言書上看到的一句話 : 程序員看到別人出現(xiàn)bug時(shí)静檬,往往會(huì)嘲笑——直到同樣的問(wèn)題出在了自己身上。并级。拂檩。至理名言。
言歸正傳嘲碧,這篇文章主要說(shuō)的是使用同一個(gè)webView多次調(diào)用 loadRequest 或者是 loadHtmlString方法時(shí)稻励,在webView釋放時(shí)會(huì)出現(xiàn)內(nèi)存泄漏的問(wèn)題。
loadRequest 和 loadHtmlString 方法算是最常用的了(沒(méi)幾個(gè)人回去用loadData)愈涩。我估計(jì)望抽,這三個(gè)load方法加矛,在加載完html之后的處理是一樣的。簡(jiǎn)而言之煤篙,就是先寫個(gè)switch斟览,區(qū)分出不同的load方式。而后舰蟆,load趣惠,之后添加手勢(shì)。
首先身害,先來(lái)看看webView的圖層結(jié)構(gòu):
webView-> webScrollView-> UIWebBrowserView味悄,最終,讓用戶能看到html內(nèi)容的塌鸯,就是UIWebBrowserView侍瑟。
從圖中可以看出,webView本生不會(huì)相應(yīng)觸摸事件丙猬。因?yàn)檎茄眨粀ebScrollView壓在身下,webScrollView又被UIWebBrowserView壓在身下茧球。所以庭瑰,即使繼承于UIWebView做一個(gè)子類,在這個(gè)子類的touchbegin 函數(shù)中也不會(huì)有任何信息抢埋。
所有的觸摸事件弹灭,其實(shí)都加在 UIWebBrowserView 上,而webview 管不著揪垄。(iOS4之前還有一個(gè)UIWebDocumentView穷吮,但這個(gè)已經(jīng)太久遠(yuǎn),不提了)UIWebBrowserView上面的觸摸事件一共有7種饥努,可以通過(guò)gestureRecognizers去看捡鱼。UIWebBrowserView是Apple的私有api,所以不能直接調(diào)用酷愧,要訪問(wèn)的話驾诈,要稍微繞一下彎。
以上是Apple的wenView的大概情況溶浴,坑出現(xiàn)在這里 —— 反復(fù)調(diào)用load方法的時(shí)候:
logs:
如圖翘鸭,在log中顯示的是調(diào)用了4次load方法后打印的結(jié)果。第一次調(diào)用 load 的時(shí)候戳葵,其實(shí)并沒(méi)有 _UITextSelectionForceGesture(私有api) 這個(gè)手勢(shì)就乓。但是從第二次調(diào)用開(kāi)始,每調(diào)用一次,_UITextSelectionForceGesture 就會(huì)被添加一次生蚁。
使用 instrument leaks check 時(shí)發(fā)現(xiàn) _UITextSelectionForceGesture 存在循環(huán)引用的問(wèn)題:
leaks check中我調(diào)用了5次load噩翠,所以看到的現(xiàn)象是有4個(gè)_UITextSelectionForceGesture泄漏了。
綜上所述邦投,對(duì)于一個(gè)webView 調(diào)用 load只有一次的話伤锚,是ok沒(méi)問(wèn)題的,但是同一個(gè)webView如果第二次志衣,第三次屯援,直到第n次的時(shí)候,會(huì)有 n - 1 個(gè) _UITextSelectionForceGesture無(wú)法釋放(觸摸事件和觀察者間循環(huán)引用了)念脯。
在webView出現(xiàn)泄漏時(shí)可以想想是不是這個(gè)情況狞洋。