- 好的習(xí)慣可以防止內(nèi)存相關(guān)的問題
a) 在反復(fù)使用同一個(gè)數(shù)據(jù)時(shí)釋放掉或者覆蓋掉。
b) 當(dāng)數(shù)據(jù)不再被使用時(shí)如果不釋放掉,會(huì)造成內(nèi)存泄露。 - 基本的內(nèi)存管理準(zhǔn)則:
a) 你擁有你創(chuàng)建的任何對(duì)象的管理權(quán)。諸如:alloc,copy,new,mutableCopy,
等待創(chuàng)建的對(duì)象適用此規(guī)則。
b) 使用了retain的對(duì)象你需要管理。
在以下兩種情況下你要使用retain:
i. 實(shí)現(xiàn)了訪問方法,或者一個(gè)init方法;
ii. 保證一個(gè)對(duì)象不被其它操作引起失效
c) 當(dāng)不需要對(duì)象時(shí),需要自己釋放這個(gè)對(duì)象。 通過releas或者autorelease方法。
d) 不能釋放一個(gè)你沒有所有權(quán)的對(duì)象。 - 通過引用返回的對(duì)象你沒有所有權(quán)
Cocoa里面的一些方法返回的是引用:(對(duì)象為ClassName ** 或者 id *),比如通過initWithContentsOfUrl:options:error: (NSData)中的NSError對(duì)象,不能隨意release。 - 在重寫setter方法時(shí),必須要在retain操作之后再進(jìn)行釋放,以免set的是相同變量。
- (void)setCount: (NSNumber *)newCount {
[newCount retain];
[_count release];
_count = newCount;
}
兩種創(chuàng)建變量的方法比較:
a) 通過NSNumber變量進(jìn)行alloc,所以需要release:
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[zero release];
b) 第二種方式是使用一個(gè)方便的構(gòu)造器來返回,因此不需要retain或者release:
NSNumber *zero = [NSNumber numberWithInteger:0];避免在使用時(shí)造成deallocing:
a) 當(dāng)對(duì)象被移除時(shí);
b) 當(dāng)指針被deallocated時(shí)Autorelease Pools:
autorelease pool 是NSAutoreleasePool的實(shí)例,在此實(shí)例中會(huì)接收autorelease消息。當(dāng)autorelease pool被dealloced,會(huì)發(fā)release消息給每一個(gè)對(duì)象。 一個(gè)對(duì)象可以被放到autorelease pool多次,每一次進(jìn)入pool時(shí)都會(huì)接收到release消息。AutoreleasePool是按照棧來存儲(chǔ)的,最近使用的pool在棧頂。
Autorelease pool應(yīng)該在以下三種情況下手動(dòng)使用:
a) 如果項(xiàng)目不是基于UI framework,比如 command-line tool
b) 如果一個(gè)循環(huán)內(nèi)有很多臨時(shí)變量。釋放這些變量有助于降低內(nèi)存峰值
c) 在線程被調(diào)用時(shí)必須啟用自己的autorelease pool,不然程序會(huì)內(nèi)存泄露。每一個(gè)線程包含自己的NSAutoreleasePool對(duì)象。當(dāng)一個(gè)線程終止時(shí),它所在的autorelease pool自動(dòng)釋放。
如果drain了不在棧頂?shù)腶utorelease pool,則所有在它之上的pool都會(huì)被drained。(所有相關(guān)的對(duì)象都會(huì)收到release)
GC沒有使用autorelease pool
在GC環(huán)境,release 不是一個(gè)命令。NSAutorelease Pool 因此提供了一種drain命令,在標(biāo)簽計(jì)數(shù)環(huán)境和調(diào)用release是等價(jià)的;在gc環(huán)境下會(huì)出發(fā)gc。所以,應(yīng)當(dāng)盡可能使用drain而非release命令。