問題1 是否所有的的對象加入了autoreleasepool?
有時候會聽到這樣的回答。ARC下一個對象創(chuàng)建的時候就會加入到自動釋放池,這顯然是不對的。
只有需要延遲釋放的對象,才會加入到autoreleasepool,那么什么是延遲釋放的對象。待會我會提到。
在MRC下 [obj retain] 計數(shù)為1, [obj release] 計數(shù)為0。obj指向的對象就釋放了。obj指針還在。那么在ARC是怎么樣的,我們都知道ARC其實也會有retain,release的操作,只是他是在編譯期自動插入在合適的地方。
問題2 什么對象會加入autoreleasepool?
在MRC下調(diào)用了 autorelease自然會加入到釋放池。那么ARC呢?
內(nèi)存管理有四個原則(MRC和ARC都適用)
1 自己生成的對象,自己所持有(alloc,new,copy,mutablecopy)
2 非自己生成的對象,自己也能持有(retain,在arc下如果A引用了B,就會對B自動retain)
3 不再需要自己持有的對象時對其釋放(release)
4 非自己持有的對象無法釋放。
5 dealloc是銷毀。retain 和release 兩個方法分別是將reference counter 加1和減1。
當(dāng)使用release方法當(dāng)reference counter值為0時會自動使用dealloc方法。
A NSString *str = [NSString alloc] init];
B NSString *str = [NSString xxx類方法];
這兩種獲取對象的方式的不同之處就是在A的對象是自己生成的。B的對象是類方法返回的。類方法的方法一般如下。
(NSString *)xxx類方法{
NSString *str = [NSString alloc] init];
//C
return str;
}
如果我要釋放這個對象就需要在C這個位置釋放。但是如果我釋放了。B這個位置及獲取不到str對象了。所以才需要延遲釋放,才需要一個自動釋放池。
問題3 加入了autoreleasepool中的對象什么時候釋放?
在沒有手加autorelease Pool的情況下,autorelease對象是在當(dāng)前的runloop迭代結(jié)束時釋放的,而它能夠釋放的原因是系統(tǒng)在每個runloop迭代中都加入了自動釋放池Push和Pop。
最后會自動對其中的對象執(zhí)行一次release。 暫時不寫autoreleasepage的結(jié)構(gòu)。
。只想問一下這里說的迭代時機是哪一個時機?
如果在迭代時機過早,為什么不會釋放了還需要使用的對象。
問題4 NSRunloop多久一次迭代,如何迭代?
NSRunloop可以簡單理解成如下循環(huán)
1(等待消息) -> 2(將要處理消息) -> 3(處理消息) -> 4(消息處理完成) -> 1(等待消息)
其中,autoreleasePool 在 4 (消息處理完成) 這個階段進行釋放。在一個消息處理中,無論包含多少層函數(shù)調(diào)用,也一直處于 3 (處理消息) 這個階段當(dāng)中。因此在當(dāng)前消息循環(huán)內(nèi),放到 autoreleasePool 的對象會一直生效,并不會被釋放。
所以,一個消息未結(jié)束,他想關(guān)聯(lián)的對象就不會被釋放掉。消息結(jié)束了,那我的事件也已經(jīng)處理完畢了,對象也用不到了。
問題5 子線程中的autoreleasepool是什么機制?
子線程默認(rèn)是沒有NSRunLoop的,那么子線程中的自動釋放池的對象是如何操作的?
如果獲取不到autoreleasePoolpage,就會創(chuàng)建一個autoreleasePoolNopage。
結(jié)構(gòu)下回分解。
測驗:
for (100000times 循環(huán)){
NSString *str = [NSString alloc] init];
}
會出現(xiàn)內(nèi)存峰值嗎?