ARC全稱為Automatic Reference Counting,也就是編譯器為我們自動添加retain/release/autorelease等語句,保證引用計數的正確性,而不需要我們自己添加,僅僅如此。ARC不代表像Java那樣有GC做垃圾回收,所以本質上還是要“手動”管理內存的。
而@autoreleasepool 可以幫助我們自動回收內存。當@autoreleasepool結束的時候,被ARC自動標記過autorelease的對象都會被release掉,也就是會被釋放掉。
有些人會有些疑問,不管是在MRC還是ARC環境下,對象retain count為0的時候,對象都會被釋放,為什么我們還要使用@autoreleasepool呢,不是多此一舉嗎?正常情況下,一個被標記為“autorelease”的對象,在retain count為0的時候,要等到當前runloop結束的時候,才會被釋放。而在當前runloop結束之前,可能會出現無數個等待被釋放而沒有被釋放的對象,這時候內存占用率就會比較高。恰當的使用@autoreleasepool可以及時釋放這些對象,降低內存的使用率。
根據Apple的文檔,@autoreleasepool使用場景如下:
- 寫基于命令行的的程序時,就是沒有UI框架,如AppKit等Cocoa框架時。
- 寫循環,循環里面包含了大量臨時創建的對象。(本文的例子)
- 創建了新的線程。(非Cocoa程序創建線程時才需要)
- 長時間在后臺運行的任務。
對于每一個Runloop(或者稱為事件周期), 系統會隱式創建一個Autorelease pool(自然會有多個Autorelease pool),這樣所有的release pool會構成一個象CallStack一樣的一個棧式結構,在每一個Runloop結束時,當前棧頂的Autorelease pool會被銷毀,這樣這個pool里的每個Object會被release。那什么是一個Runloop呢? 一個UI事件,Timer call, delegate call, 都會是一個新的Runloop。