2009-04-26 47 views
1

蘋果在setter方法是這樣做的一個實例變量mainSprocket:爲什麼要在setter方法中將-autorelease發送給我的實例變量,而不是釋放?

– (void)setMainSprocket:(Sprocket *)newSprocket { 
    [mainSprocket autorelease]; 
    mainSprocket = [newSprocket retain]; 
    return; 
} 

他們爲什麼要送-autorelease而不是-release?在這裏會有一個不好的結果嗎?實際上它不應該(因爲我的理解),因爲-release只是說實例變量mainSprocket保存的當前對象不再被該實例變量使用。對於其他人仍然對該對象感興趣的情況,該方法可以保留它,對嗎?所以 - 我覺得釋放應該沒問題?

回答

3

他們在做autorelease這裏newSprocketmainSprocket碰巧是同一個對象。對release的調用可能會意外釋放對象,然後才能保留在下一行,而autorelease將不會被處理,直到自動釋放池在事件循環結束時耗盡爲止。

考慮這種情況:

Sprocket *mySprocket = [Sprocket spacelySprocket]; 
[sprocketManager setMainSprocket:mySprocket]; 

Sprocket *anotherPointerToMySprocket = mySprocket; 
[sprocketManager setMainSprocket:anotherPointerToMySprocket]; 

最後一行將導致一個問題,如果mainSprocket沒有自動釋放。你有時會看到二傳手代碼做同樣的事情的另一個約定是:

– (void)setMainSprocket:(Sprocket *)newSprocket { 
    if (newSprocket != mainSprocket) { 
     [mainSprocket release]; 
     mainSprocket = [newSprocket retain]; 
    } 
} 

我將留給其他人來發表評論,這是比較合適的或美觀的:-)

+0

感謝。但是,如果它不是同一個對象,並且我多次調用該方法,是否會遇到與autorelease池有關的問題?因爲該池可能只在應用程序的主要功能中耗盡? – Thanks 2009-04-26 11:25:33

+0

如果您在創建大量對象的函數中,您可以自行排空自動釋放池。 – 2009-04-26 11:29:53

4

如果mainSprocketnewSprocket是相同的對象,如果您使用簡單的release它可能會被釋放。

如果你不想使用autorelease,使用此:

– (void)setMainSprocket:(Sprocket *)newSprocket { 
    // if newSprocket and mainSprocket were the same object, 
    // it would first be retained and then released 
    // and therefore not deleted. 
    [newSprocket retain]; 
    [mainSprocket release]; 
    mainSprocket = newSprocket; 
    // you don't need return in a void-method 
    // return; 
} 

你爲什麼不使用屬性?它們是Objective-C 2.0的做法。

SomeObject.h

@interface SomeObject : NSObject { 
    Sprocket *mainSprocket; 
} 

@property(retain) Sprocket *mainSprocket; 

@end 

SomeObject.m

@implementation SomeObject 

@synthesize mainSprocket; 

@end 
相關問題