第四章 內(nèi)存管理
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init ]; [pool drain];
事實上程序中可以有多個自動釋放池。自動釋放池其實并不包含實際的對象本身,僅僅是對釋放的對 象的引用。通過向目前的自動釋放池發(fā)送一條autorelease 消息,可以將一個對象添加到其中。
引用計數(shù):
概念:創(chuàng)建對象時,將它的引用次數(shù)設(shè)置為1,每一次必須保持該對象時,就發(fā)送一條retain 消息, 使其引用次數(shù)加 1。
[myFraction retain];
不再需要對象時,可以通過發(fā)送 release 消息,使對象的引用次數(shù)減 1。 [myFraction release];
當(dāng)引用計數(shù)為 0 的時候,系統(tǒng)就會釋放它的內(nèi)存,通過向?qū)ο蟀l(fā)送dealloc 消息。通過向?qū)ο蟀l(fā)送 retainCount 消息可以獲得這個對象的引用計數(shù), 返回的是NSUInteger 整數(shù)。 只要對象的引用計數(shù)不為0, 系統(tǒng)就不會釋放對象使用的內(nèi)存。
將對象添加到任何類型的集合中都會使該對象的引用計數(shù)增加。從任何集合中刪除對象都能夠使其引 用計數(shù)減少。
內(nèi)存中常量字符串沒有引用計數(shù)機(jī)制,因為永遠(yuǎn)不能釋放這些對象。這也適用于使用常量字符串初始 化的不可變字符串對象。
當(dāng)某段代碼需要訪問一個對象的時候, 將對象的引用計數(shù)器加1, 當(dāng)其為0 表明不再有代碼訪問該對象 了,即對象將被銷毀(通過調(diào)用dealloc 方法) 。
一個簡單的示例:
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
RetainTracker *tracker;
tracker = [RetainTracker new]; // count: 1
[tracker retain]; // count: 2
[tracker autorelease]; // count: still 2
[tracker release]; // count: 1
NSLog (@"releasing pool");
[pool release];
// gets nuked, sends release to tracker
return (0);
}
當(dāng)使用 alloc、new 或者通過 copy 消息(生成接受對象的一個副本)創(chuàng)建一個對象,對象的引用計數(shù) 器被設(shè)置成 1。發(fā)送 retain 消息將增加引用計數(shù)器,release 消息減 1。
要獲得引用計數(shù)器的當(dāng)前值,可以發(fā)送retainCount 消息
- (id) retain ;
- (void) release ;
- (unsinged) retainCount ;
訪問方法中的保留和釋放: 最好的方法設(shè)置的原則是(保持新的釋放舊的,誰擁有對象誰就復(fù)制釋放對象)
- (void ) setEngine : (Engine *) newEngine {
[newEngine retain] ; [engine release] ; engine = newEngine;
}
內(nèi)存管理規(guī)則
獲得途徑
臨時對象
擁有對象
alloc/new/copy
不再使用時釋放對象
在 dealloc 方法中釋放對象
任何其他方法
不需要執(zhí)行任何操作
獲得對象時保留,在 dealloc 方法中釋放對象
內(nèi)存管理規(guī)則摘要: 1、釋放對象,可以釋放其所占的內(nèi)存,規(guī)則是:不再使用創(chuàng)建或者保持的對象時,就釋放它們。 2、發(fā)送一條 release 消息不一定銷毀對象,只有引用計數(shù)變?yōu)? 時,才銷毀這個對象。系統(tǒng)向
對象發(fā)送一條 dealloc 消息來釋放它所占的內(nèi)存。 3、自動釋放池在釋放池本身的時候自動釋放池中的對象。系統(tǒng)向每個對象發(fā)送一條release 消
息,對引用計數(shù)變?yōu)?0 的對象發(fā)送一條 dealloc 消息來釋放它所占的內(nèi)存。 4、若你的方法中不再需要一個對象時,但需要返回它,可發(fā)送一條autorelease 消息來加入自
動釋放池。
5、若使用 alloc 或 copy 方法(或使用 allocWithZone:、copyWithZone:或 mutableCopy 方法
來直接創(chuàng)建對象,則由你負(fù)責(zé)釋放它。每次retain 對象時,應(yīng)該 release 或 autoreleas 它。 6、除了上以規(guī)則中提到的方法之外,不必費心地釋放其他方法返回的對象,這不是你的責(zé)任。