autorelease的對象什么時候被回收

主線程有個事件循環(huán)。每次有事件的時候,由cocoa框架調(diào)用我們寫的代碼,再回到cocoa框架。NSAutoreleasePool其實是由cocoa框架管理的,當(dāng)出了我們寫的代碼,回到框架的時候,放入NSAutoreleasePool的對象就會由框架調(diào)用release, 這樣就保證跑我們代碼的時候,對象是會存在的,出了我們的代碼,對象也能夠正常地被釋放。

比如

系統(tǒng)代碼(事件激發(fā))

funA()

funB()

funC()

funD()

系統(tǒng)代碼(等待事件)

在funA, funB, funC, funD中,無論調(diào)用多少層,也是用戶寫的代碼。autorelease的對象還是存在的。下一次事件激發(fā)的時候,上一次事件的對象是不存在的,因為已經(jīng)被系統(tǒng)框架調(diào)用release回收了。除非你自己調(diào)用了retain, 自己調(diào)用了一次retain, 就應(yīng)該自己來調(diào)用一次release, 這樣也沒有違背上面說的原則。

自動釋放池的缺點:它延緩了對象的釋放,在有大量自動釋放的對象時,會占用大量內(nèi)存資源。因此,你需要避免將大量對象自動釋放。并且,在以下兩種情況下,你需要手動建立并手動銷毀掉自動釋放池:

1.當(dāng)你在主線程外開啟其它線程時:系統(tǒng)只會在主線程中自動生成并銷毀掉自動釋放池。(runloop未開啟)

2.當(dāng)你在短時間內(nèi)制造了大量自動釋放對象時:及時地銷毀有助于有效利用iPad上有限地內(nèi)存資源


iOS的運行時是由一個一個runloop組成的,每個runloop都會執(zhí)行下圖的一些步驟:

可以看到,每個runloop中都創(chuàng)建一個Autorelease Pool,并在runloop的末尾進(jìn)行釋放,

所以,一般情況下,每個接受autorelease消息的對象,都會在下個runloop開始前被釋放。也就是說,在一段同步的代碼中執(zhí)行過程中,生成的對象接受autorelease消息后,一般是不會在代碼段執(zhí)行完成前釋放的。

當(dāng)然也有讓autorelease提前生效的辦法:自己創(chuàng)建Pool并進(jìn)行釋放

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

NSArray* array = [[[NSArrayalloc] init] autorelease];

[pool drain];

上面的array就會在[pool drain]執(zhí)行時被釋放。

所以對于你遇到的問題,可以在for循環(huán)外嵌套一個Autorelease Pool進(jìn)行管理,例如

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

for(inti =0; i <10000; i++)

{// ...}

[pool drain];

但由于你提到了生成的每個實例可能會比較大。只在循環(huán)外嵌套,可能導(dǎo)致在pool釋放前,內(nèi)存里已經(jīng)有10000個實例存在,造成瞬間占用內(nèi)存過大的情況。

因此,如果你的每個實例僅需要在單次循環(huán)過程中用到,那么可以考慮可以在循環(huán)內(nèi)創(chuàng)建pool并釋放

for(inti =0; i <10000; i++)

{NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc] init];

// ...[pool drain];}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容