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