您好,登錄后才能下訂單哦!
在本章,你將學(xué)到:
復(fù)習(xí)舊的手工內(nèi)存管理的策略
對(duì)象所有權(quán)策略
基于舊的手工內(nèi)存管理之上的新的自動(dòng)內(nèi)存管理
什么是對(duì)象的拷貝以及如何使用它
如何恰當(dāng)?shù)氖褂胊utorelease和release方法
復(fù)習(xí)內(nèi)存測(cè)量
iPhone是一個(gè)內(nèi)存有限的環(huán)境。但是,很多開發(fā)者要么低估了它,要么高估了它,因此并沒有利用好iPhone上的可用內(nèi)存來提升性能。還有一些開發(fā)者非常擔(dān)心iPhone上的內(nèi)存和性能,以至于他們過度優(yōu)化,這樣其實(shí)對(duì)代碼的可閱讀性是非常有害的,也使得日后的維護(hù)變得更加困難。
為了有效利用內(nèi)存來提升性能,同時(shí)使代碼更容易閱讀,又不讓應(yīng)用崩潰,你需要理解iPhone環(huán)境下的內(nèi)存結(jié)構(gòu)。你需要學(xué)習(xí)如何避免在內(nèi)存在中過多引用對(duì)象,它能夠?qū)е聝?nèi)存警告和程序崩潰。你同樣需要知道何時(shí)retain或release一個(gè)對(duì)象;如果在內(nèi)存中的對(duì)象太少,可能會(huì)使得你的計(jì)算變得緩慢,因?yàn)槟阈枰匦聵?gòu)造對(duì)象或從文件系統(tǒng)中加載。
簡(jiǎn)單的回顧
本部分是學(xué)習(xí)新的自動(dòng)引用計(jì)數(shù)(ARC)的一個(gè)很好的過渡。有些人可能對(duì)于轉(zhuǎn)到新的課程會(huì)有些迷惑。我希望本部分能夠幫助你非常順利的過渡到新的ARC機(jī)制上。
舊的對(duì)象所有權(quán)策略
如果A對(duì)象有B對(duì)象的一個(gè)強(qiáng)引用,那么A對(duì)象需要手動(dòng)的release對(duì)象B,這是舊的概念。如果A對(duì)象alloc,copy,mutableCopy,new或retain對(duì)象B,那么A對(duì)象就有了對(duì)象B的強(qiáng)引用。另一方面,如果A對(duì)象沒有使用這些方法,那么A對(duì)象擁有B對(duì)象的弱引用。
對(duì)于舊的內(nèi)存管理機(jī)制,如果你的對(duì)象或方法有另一個(gè)對(duì)象B的強(qiáng)引用,你有責(zé)任release或autorelease對(duì)象B。每一個(gè)B對(duì)象的強(qiáng)引用都會(huì)使得它的引用計(jì)數(shù)加1。如果沒有任何對(duì)象擁有B對(duì)象的強(qiáng)引用,換句話說,B對(duì)象的引用計(jì)算為0,B對(duì)象就會(huì)被deallocated(Listing 7.1)。
Listing 7.1. Release the Object if You Have a Strong Reference
- (void)doSomething {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@", obj);
[obj release];
}
AutoRelease
autorelease方法會(huì)將對(duì)象發(fā)送到一個(gè)池中,然后聲明這個(gè)對(duì)象稍后將要被release掉。使用這個(gè)方法,你不想擁有任何對(duì)象的強(qiáng)引用,但是你也不想它被dellocated。請(qǐng)查看Listing 7.2 。
Listing 7.2. Memory Issue
- (NSObject *)getObj {
NSObject *obj = [[NSObject alloc] init];
return obj;
}
- (void)anotherMethod {
NSObject *myObj = [self getObj];
// do something
// Should I release the object here?
[myObj release];
}
現(xiàn)在,在你使用完一個(gè)對(duì)象后,你要問問自己是否需要release它。通常,你可能會(huì)認(rèn)為要release它;否則,沒人release它,那么就會(huì)發(fā)生內(nèi)存泄露。但是,因?yàn)槟愕腶notherMethod方法沒有myObj的強(qiáng)引用,你不能release myObj。唯一的辦法就是像Listing 7.3 使用autorelease。
Listing 7.3. Use Autorelease to Solve the Problem
- (NSObject *)getObj {
NSObject *obj = [[NSObject alloc] init];
return [obj autorelease];
}
- (void)anotherMethod {
NSObject *myObj = [self getObj];
// do something
}
注意:anotherMethod沒有其他對(duì)象的強(qiáng)引用。 |
Autorelease
我會(huì)快速的帶你復(fù)習(xí)一下autorelease pools,然后深入的解釋一下相關(guān)概念,這樣你就能夠理解autorelease pool和release之間的不同。
autorelease pool是存放autoreleased對(duì)象的地方。當(dāng)這個(gè)autorelease pool被release時(shí),所有的autoreleased對(duì)象會(huì)發(fā)送一個(gè)release消息。如果一個(gè)對(duì)象的引用計(jì)數(shù)為0,那個(gè)這個(gè)對(duì)象就會(huì)被deallocted。
在事件聲明周期結(jié)束的時(shí)候,autorelease pool會(huì)被release。例如,當(dāng)用戶觸摸了UI,一個(gè)新的事件聲明周期會(huì)被創(chuàng)建來處理這次觸摸事件,然后它處理相關(guān)觸摸事件的所有理解,最后顯示給用戶。這就是一個(gè)事件聲明周期。對(duì)于這個(gè)事件聲明周期,你會(huì)有一個(gè)autorelease poo。
在main 方法中創(chuàng)建一個(gè)main autorelease pool,可以使用下面的代碼:
int main(int argc, char *argv[]) {
@autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, nil);
}
return retVal;
}
在代碼中可以看到,在方法的開始部分,創(chuàng)建了一個(gè)新的autorelease pool,使用了UIApplicationMain處理了主要的邏輯;在事件循環(huán)之后,pool被release。整個(gè)周期如圖7-1.
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。