偶然發(fā)現(xiàn)自己的 ViewController 退出后沒有釋放,存在內(nèi)存泄露,而代碼量大的情況下自己找可能的 retain cycle 不太現(xiàn)實(shí),于是學(xué)習(xí)了用官方的 Instruments 工具來找出代碼的問題。
一、打開 Instruments
If Instruments has access to information about your app’s source code, a leak is reported as a class name. Otherwise, a leak is reported as a memory address, such as Malloc-size. To ensure that Instruments has access to information about your code, initiate profiling from Xcode (see Profile from Xcode) or configure a symbol mappings file (see Map Data to Source Code).
上面這段話來自 Apple 官方文檔Find Memory Leaks厘惦。
在開始之前,為了確保 Instruments 可以訪問到代碼從而更好地定位問題哩簿,需要在 Xcode 中執(zhí)行 Profile宵蕉。首先在 Xcode 中 build 或 run 最新代碼,成功后選擇菜單欄中的 Product->Profile(或快捷鍵 Cmd+I)节榜,完成后在彈出的菜單中選擇 Leaks国裳,如圖:
二、使用 Leaks 定位問題
點(diǎn)擊紅色圓圈按鈕全跨,即可 luanch app缝左,并開始錄制內(nèi)存使用情況。界面如圖:
默認(rèn)顯示 Statistics 詳情面板浓若。為了迅速篩選出感興趣的 allocation渺杉,可以在底部輸入框中輸入相關(guān)關(guān)鍵字,例如「viewcontroller」挪钓,這樣就只剩下項(xiàng)目相關(guān)的 view controller 了:
其中是越,兩個(gè)需要關(guān)注的數(shù)據(jù)欄是 # Persistent
和 # Transient
:# Persistent
表示現(xiàn)在在內(nèi)存中各個(gè)類別的 object 的數(shù)量,正在使用內(nèi)存碌上;而 # Transient
表示存在過但是目前已被銷毀的 object 的數(shù)量薪贫,其占用的內(nèi)存已被釋放蝉娜。
操作若干次后园匹,內(nèi)存分配情況如圖:
可以明顯地看出深纲,ConferenceViewController
目前存在 4 個(gè),釋放過的個(gè)數(shù)為 0霞丧。因此該 view controller 有內(nèi)存泄露呢岗。點(diǎn)擊 type 右側(cè)箭頭(如圖中所示):
可以看到 4 個(gè) object 的地址、大小蛹尝、代碼來源等信息后豫。點(diǎn)擊地址右側(cè)箭頭,可以進(jìn)一步看到詳細(xì)的引用計(jì)數(shù)變化情況突那。點(diǎn)擊與項(xiàng)目代碼相關(guān)的使引用計(jì)數(shù)增加的一行挫酿,可以看到右側(cè)的 stack trace 信息:
圈出的黑色部分,即項(xiàng)目的相關(guān)調(diào)用愕难。雙擊最上面的一行早龟,左側(cè)詳情面板出現(xiàn)了具體代碼惫霸,接下來即可根據(jù)有顏色的提示找到項(xiàng)目的具體問題。
對(duì)于示例拄衰,很顯然是 - (void)loadData
函數(shù)出了問題。最常見的情況就是傳遞給將要保存的 block 中強(qiáng)引用了 self
饵骨,導(dǎo)致 retain cycle翘悉。改為對(duì) self 的弱引用,再重復(fù)上述步驟居触,可以看到反復(fù)操作后妖混,# Transient
的數(shù)量正常增加了。
三轮洋、結(jié)語
以上是 Leaks 工具快速查找 memory leak 的一個(gè)用法制市,還有其他方法可以查看 allocation 情況,但在本例中對(duì)作者幫助不大弊予,就不詳細(xì)列出了祥楣。可以參考官方文獻(xiàn) Find Memory Leaks汉柒,和文章 Instruments Tutorial with Swift: Getting Started误褪,有更詳細(xì)的用法講解。