一對夫婦的想法:
最好的做法是不寫setter方法可言,採取的自動合成存取方法的優勢)。編寫你自己的只是一個搞亂內存管理或引入錯誤的機會。在寫一個自定義setter之前,你應該有一個引人注目的需求。
實例變量名稱的新興慣例是使用前面帶有下劃線的屬性名稱(例如,對於稱爲name
的財產,伊娃爲_name
)。如果您省略了@synthesize
語句,則最新版本的Xcode附帶的編譯器會自動爲您執行此操作。
在沒有說明你的財產有什麼記憶限定符的情況下,設置者應該是什麼的問題是沒有意義的。我假設你將你的財產定義爲retain
。
將屬性更改爲NSMutableString
會改變屬性的行爲,我不會建議,除非您確實需要可變字符串。
如果有人將name
屬性設置爲nil
,則第一個示例不會執行任何操作。但是如果有人想將其設置爲nil
,則應該(a)釋放舊的name
值;和(b)將你的伊娃放入nil
。 (順便說一句,下面的代碼利用了將消息發送到nil
對象沒有任何作用的事實,所以在這種情況下,我不需要檢查它是否爲nil
。)
所以,我假設你有一個屬性定義如下:
@property (nonatomic, retain) NSString *name;
和合成線被省略或看起來像:
@synthesize name = _name;
然後,我想二傳手將如下所示:
-(void) setName:(NSString *)name
{
// if you want to program defensively, you might want the following assert statement:
//
// NSAssert(name == nil || [name isKindOfClass:[NSString class]], @"%s: name is not string", __FUNCTION__);
if (name != _name)
{
[_name release];
_name = name;
[_name retain];
}
}
順便說一句,我假設你的init
方法正確初始化_name
和dealloc
釋放它。
- (id)init
{
self = [super init];
if (self) {
_name = nil;
}
return self;
}
- (void)dealloc
{
[_name release];
[super dealloc];
}
由於bblum指出,這是謹慎使用copy
您NSString
屬性:
@property (nonatomic, copy) NSString *name;
然後,我覺得二傳手會是什麼樣子:
-(void) setName:(NSString *)name
{
// if you want to program defensively, you might want the following assert statement:
//
// NSAssert(name == nil || [name isKindOfClass:[NSString class]], @"%s: name is not string", __FUNCTION__);
if (name != _name)
{
[_name release];
_name = [name copy];
}
}
但真的,除非你絕對需要,否則你根本不應該寫西班牙文。
最後,您的代碼有關於查找內存管理混淆的註釋。雖然你一定要明白,我會做最後兩個建議:
考慮使用Automatic Reference Counting(ARC)。雖然這並不排除理解內存管理如何工作的需要(請參閱Advanced Memory Management Programming Guide),但它確實可以更輕鬆地編寫正確處理內存管理的代碼。如果您編寫手動引用計數(MRC)代碼,那麼可以很容易地發生簡單的內存管理錯誤,否則ARC會爲您處理這些錯誤。
特別是如果你要(以下簡稱「產品」菜單上的「分析」或按轉變 + 命令 + 乙)使用MRC,利用自己的Xcode的靜態分析儀。這可以促進尋找困擾MRC代碼的許多常規內存管理問題。 儀器用戶指南的Finding Memory Leaks部分也說明了如何在調試代碼時發現泄漏,但通常靜態分析器只能通過檢查代碼來識別問題。
來源
2013-05-30 14:27:38
Rob
你爲什麼要實現自己的「setter」方法?除非您在此發佈的內容除非您實際上有其他處理方式,否則沒有必要執行此操作。 – rmaddy
@maddy我敢打賭,OP是從一個過時的教程或書籍工作。 – bbum