2011-06-28 57 views
0
- (void)setSomeInstance:(SomeClass *)aSomeInstanceValue 
{ 
    if (someInstance == aSomeInstanceValue) 
{ 
    return; 
} 
SomeClass *oldValue = someInstance; 
someInstance = [aSomeInstanceValue retain]; 
[oldValue release]; 
} 

好的,所以setter應該看起來像。我理解前三行 - 防止在新對象與舊對象相同的情況之前。 但是關於這條線是什麼:iOS中的默認設置器

SomeClass *oldValue = someInstance; 

爲什麼系統必須保持舊對象的地址。爲什麼不能把它簡單地

[someinstance release]; 
    someinstance = [aSomeInstanceValue retain]; 

回答

2

其實 - 沒有理由。

它通常只是一個選擇。

寫作存取符有三種習語。

自動釋放

- (void)setFoo:(id)newFoo { 
    [foo autorelease]; 
    foo = [newFoo retain]; 
} 

更少的代碼來寫,但我認爲自動釋放在這種情況下,懶惰。

保留然後釋放

- (void)setFoo:(id)newFoo { 
    [newFoo retain]; 
    [foo release]; 
    foo = newFoo; 
} 

首先檢查

- (void)setFoo:(id)newFoo { 
    if ([foo isEqual:newFoo]) { 
     return; 
    } 
    [foo release]; 
    foo = [newFoo retain]; 
} 

最後兩者之間的唯一區別是,第二檢查是否新的值是當前的不同嘗試設置屬性之前的值。以額外的if語句爲代價。所以 - 如果新值可能與舊值相同,那麼使用這種結構可以提供更好的性能。

通常情況下,如果您因某種奇怪的原因未使用屬性,請使用retain然後釋放,然後如果分析顯示存在瓶頸 - 請使用檢查第一種方法。

+2

我會讓最後一個陳述更強大; **如果您的設置者沒有特殊行爲,則應始終使用@property和@synthesize。如果你的設置者有特殊的行爲,你應該重新考慮你的架構。**具有自定義行爲的設置者在不斷髮展的代碼庫中是一個永無止境的痛苦源泉。 – bbum

+0

當屬性發生變化時,需要更新的對象怎麼樣?我用了很多,並且從來沒有真正的嚴重問題。 – huesforalice

+0

有很多理由使用自定義setter和getter。 Paul Hegarty在他的課程中給出了很多例子。確保沒有設置值的默認值是1。 - (CGFloat)scale if(!_scale){ return DEFAULT_SCALE; //不允許零刻度 }其他{ return _scale; } } – JScarry

0

默認保留二傳手就像是:

- (void)setFoo:(Foo *)aFood 
{ 
    if (_foo != nil) 
     [_foo release]; 
    if (aFood != nil) 
     _foo = [aFood retain]; 
} 
+2

檢查零是沒有必要的,因爲發送消息到零返回nil立即。 – vikingosegundo

+0

那麼如果_foo == aFood呢? – juantorena

+0

這不是默認setter如何工作的原因@juantorena確定的原因。 – bbum

2

我建議保留默認工作setter方法是這樣的:

- (void) setFoo:(id) foo { 
    if (foo == _foo) return; 
    [_foo release]; 
    _foo = [foo retain]; 
} 

,如果你不要檢查舊的和新的foo是否相同,如果你出於某種原因寫下如下內容,最終可能會引用一個釋放對象:

myObject.foo = myObject.foo; 

因爲同一個對象首先被釋放,然後被保留。如果myObject是唯一所有者,那麼在第一次發佈後,該對象將被釋放,留下一個懸掛指針。