2010-03-12 76 views
1

愚蠢的問題,但爲什麼我們需要在聲明屬性時使用'retain'?無論如何,當它被分配了一些東西時它不會被保留嗎?objective-c 2.0屬性和'保留'

看一下這個例子,似乎一個對象在分配時會自動保留,所以有什麼意義呢?

#import "Fraction.h" 
#import <stdio.h> 

int main(int argc, const char *argv[]) { 
    Fraction *frac1 = [[Fraction alloc] init]; 
    Fraction *frac2 = [[Fraction alloc] init]; 

    // print current counts 
    printf("Fraction 1 retain count: %i\n", [frac1 retainCount]); 
    printf("Fraction 2 retain count: %i\n", [frac2 retainCount]); 

    // increment them 
    [frac1 retain]; // 2 
    [frac1 retain]; // 3 
    [frac2 retain]; // 2 

    // print current counts 
    printf("Fraction 1 retain count: %i\n", [frac1 retainCount]); 
    printf("Fraction 2 retain count: %i\n", [frac2 retainCount]); 

    // decrement 
    [frac1 release]; // 2 
    [frac2 release]; // 1 

    // print current counts 
    printf("Fraction 1 retain count: %i\n", [frac1 retainCount]); 
    printf("Fraction 2 retain count: %i\n", [frac2 retainCount]); 

    // release them until they dealloc themselves 
    [frac1 release]; // 1 
    [frac1 release]; // 0 
    [frac2 release]; // 0 

■輸出

級分1保留計數:1個

級分2保留計數:1個

級分1保留計數:3

級分2保留計數:2

分數1保留數:2

部分2保持數:1

Deallocing分數

Deallocing分數


這是推動我瘋了!

回答

3

屬性的默認行爲是ASSIGN,而不是RETAIN。這些行爲不一樣。如果你的屬性是用於原始數據類型的,比如int,那麼ASSIGN就可以正確使用。但是,如果指定(保留)並且該屬性指向諸如NSObject *對象之類的對象指針,則將爲該指針分配對象的內存地址,並將其保留計數加1。如果你的程序只包含一個單獨的主要功能,那麼它的目的很難看到。但是,假設你的類有這個方法:

-(void)setMyArrayWithString:(NSString *)s{ 
    myArray = [NSArray arrayWithObject:s]; 
    } 

假設myArray的被定義爲NSArray的* myArray的,並有適當的@property(保留)聲明。 一切正常,直到方法返回。這是因爲從NSArray返回的對象是一個自動釋放對象。如果我們不保留它,它將被NSAutoReleasePool發佈,我們將無法使用它(並且我們會得到令人討厭的錯誤和錯誤的訪問衝突)。爲了解決這個問題,我們可以做以下兩件事之一:

-(void)setMyArrayWithString:(NSString *)s{ 
    self.myArray = [NSArray arrayWithObject:s]; 
// OR 
    myArray = [[NSArray arrayWithObject:s] retain];  
} 

第一個解決方案使用self.myArray來利用@property定義。此代碼分配並保留該對象,以便在函數返回時不會丟失它。第二種解決方案手動設置NSArray * myArray指針,然後手動保留NSArray對象。無論是哪種方式,NSAutoreleasePool都會在函數結束時釋放對象,但是它不會被釋放,因爲我們仍然保留之前保留的對象。

+0

這樣一個方法中創建的自動釋放對象在方法返回時被釋放?我不知道..我以爲你必須autorelease它,然後它掛起,直到你釋放池? – Adam 2010-03-12 04:52:30

+0

@Adam 這取決於NSAutoreleasePool對象已被放置到什麼位置。如果您正在創建一個非Cocoa應用程序,並且您在其中明確創建了NSAutoreleasePool,那麼在清除該池時就取決於您。但是,如果您使用的是Cocoa框架(如AppKit或UIKit),則當您創建autorelease對象時,它們將放入由Cocoa管理的池中。在運行循環期間,每隔一段時間,可可都會消耗游泳池。因此,如果您正在使用您不管理的池(例如可可),則保留在方法返回後必須存活的對象。 – 2010-03-12 05:52:52

+0

好吧有道理 - 謝謝! – Adam 2010-03-12 06:19:49