溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

iOS優(yōu)化內(nèi)存,提升性能 之一

發(fā)布時(shí)間:2020-07-30 08:57:14 來源:網(wǎng)絡(luò) 閱讀:642 作者:iKingLai 欄目:移動(dòng)開發(fā)

在本章,你將學(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,可以使用下面的代碼:


  1. int main(int argc, char *argv[]) {

      @autoreleasepool {
           int retVal = UIApplicationMain(argc, argv, nil, nil);

       }

        return retVal;

  2. }


在代碼中可以看到,在方法的開始部分,創(chuàng)建了一個(gè)新的autorelease pool,使用了UIApplicationMain處理了主要的邏輯;在事件循環(huán)之后,pool被release。整個(gè)周期如圖7-1.


iOS優(yōu)化內(nèi)存,提升性能 之一

向AI問一下細(xì)節(jié)

免責(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)容。

AI