記憶體管理是 iOS 裡一大重要內容,經歷過 MRC 時代的開發者或多或少都被引用計數折磨過,後來蘋果推出了 ARC (Automatic Reference Counting),這一技術大大減輕了記憶體管理的工作量,也降低了因記憶體管理而出錯的概率。但在 ARC 下還是有一些場景會導致記憶體洩漏,例如迴圈引用、強引用不再使用的物件。
Instruments Leaks
我寫了一個 Demo 來進行下面的演示,列舉了 3 種記憶體洩漏的場景,頁面截圖如下所示:
- Strong reference 是用一個陣列強引用了一個 ViewController,導致這個 ViewController 退出 navigation stack 後還被強引用引起記憶體洩漏
- Block retain cycle 就是常見的 block 導致的迴圈引用
- NSTimer retain cycle 是常見的 NSTimer 導致的迴圈引用
要檢測記憶體洩漏我們首先想到的是用 Instruments 的 Leaks 來檢測,對以上 3 種情形分別不斷 push、pop 後的結果如下所示:
Strong reference:
Strong normal:
Block retain cycle:
Block normal:
Timer retain cycle:
Timer normal:
Leaks 裡還有一個選項 Cycles & Roots 能夠分析出有迴圈引用的地方,如下圖所示:
通過以上截圖我們發現只有 block 導致的迴圈引用能夠被 Leaks 檢測出來,但是總的記憶體使用情況只增不減肯定是有問題的,下面我們使用 Allocations 進行更具體的分析。
Instruments Allocations
我們選擇 Allocations 重新開始分析,和上面一樣不斷進行 push、pop 操作,結果如下圖所示:
再對比沒有記憶體洩漏的情況:
通過以上對比我們可以看出正常情況下 push 再 pop 後對應的 ViewController 就被釋放了,Total 這一欄裡也就不會被列出;而有記憶體洩漏的類會被列出,這樣我們就找出了具體的類,然後就可以針對這個類的使用情況再深入排查可能會出現記憶體洩漏的地方。
Record reference counts
如果要更進一步檢視某一個類的引用計數情況,我們可以開啟 Record reference counts,具體操作如下圖所示:
開啟這個選項後我們再進行前面的操作,結果如下圖所示:
總結
雖然使用了 ARC 後能夠大大避免記憶體洩漏的出現,但還是會有一些場景會導致記憶體洩漏,上述例子裡的場景都還是比較常見比較容易避免的,在呼叫鏈長的時候一些迴圈引用就比較難被發現了,因此我們在開發完一個功能模組後使用 Instruments 系統的檢測一遍是比較好的習慣。
大家也可以下載這個 Demo 用 Instruments 實際操作體驗一遍,enjoy~