天天看點

蘋果如何實作 autorelease

autorelease是蘋果引以為傲的地方,它為程式開發人員減輕了很大的開發壓力,下面就介紹下autorelease。

autorelease ,顧名思義,就是自動釋放,它看上去就像是ARC,其實他更像C語言裡面的自動變量(局部變量),

C語言裡面的局部變量,就是當變量超出其作用域以後,該自動變量就會被自動抛棄。下面複習下C語言裡面的自動變量

-(void)getIt

{

   int a =0;

}

audiorelease會像C語言裡面對待自動變量那樣,對待執行個體對象,當超出其作用域的時候,對象執行個體的release方法就會被調用,同自動變量不同的是,對象的作用域可以右程式開發人員自己設定。

autorelease的具體使用方法是:1)、生成并持有NSAutoReseasePool對象。2)、調用已配置設定對象的autorelease執行個體方法。3)、廢棄NSAutoReseasePool對象

-(void)objcAutorelease

{

    NSAutoreleasePool * autoreleasePool = [[NSAutoreleasePoolalloc]init];

   id objc = [[NSObjectalloc]init];

    [objcautorelease];

    [autoreleasePooldrain];

}

其實需要注意的是,如果大量對象autorelease,隻要NSAutoreleasePool沒有被廢棄,那麼生成的對象就不能被釋放,就會導緻記憶體不足,典型的例子是讀入大量的圖檔,并且改變圖檔的尺寸,圖像檔案讀入到NSData對象,并從中生成UIImage對象,這種情況會産生大量的autorelease對象,

for (int i =0; i<10000; i++) {

}

是以可以看出上面的理智是有問題的,是以我們需要在适當的位置,生成、持有、廢棄NSAutoreleasePool對象

for (int i =0; i<10000; i++) {

       NSAutoreleasePool * autoreleasePool = [[NSAutoreleasePoolalloc]init];

        [autoreleasePooldrain];

}

其實在cocoa中,有很多類方法傳回autorelease對象,比如說

NSArray * arr1 = [NSArrayarray];//裡面已經存在autorelease

NSArray * arr2 = [[[NSArrayalloc]init]autorelease];

NSMutableArray * mutableArr1 = [NSMutableArrayarrayWithCapacity:2];

NSMutableArray *mutableArr2 = [[[NSMutableArrayalloc]initWithCapacity:2]autorelease];

arr1 和arr2 mutableArr1和mutableArr1都是一個道理。

其實autorelease的實作,我們可以追溯到源代碼

id  obj  = [[NSObjectalloc]init];

[obj autorelease];

其實obj内部實作應該是如下方式

-(void)autorelease

{

    [NSAutoreleasePooladdObject:self];

}

autorelease的實質方法的本質就是調用了 NSAutoreleasePool對象的 addObject的類方法

那到底蘋果自己是如何處理NSAutoreleasePool的呢?它的内部實作應該是怎麼樣的呢,我們可以簡單的如下猜想

NSAutoreleasePool調用的addObject方法如下:

+(void)addObject:(id)anObject

{

    NSAutoreleasePool * autoreleasePool =//取得正在使用NSAutoreleasePool的對象;

   if (autoreleasePool) {

        [autoreleasePool addObject:anObject];

    }else{

        //對象非存在狀态下調用autorelease

    }

}

然後是 NSAutoreleasePool 的對象autoreleasePool調用 addObject:方法,此時被autorelease的該對象,将會被添加到正在使用的NSAutoreleasePool裡面。

那NSAutoreleasePool的對象能不能autorelease呢?

答案是不能的,如果你調用

[autoreleasePoolautorelease];就會出現異常

控制台你會看到

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSAutoreleasePool autorelease]: Cannot autorelease an autorelease pool'

繼續閱讀