2009-02-25 69 views
16

我正在查看Apple的示例應用程序EditableDetailView,並注意到在他們的控制器之一中,他們正在使用(nonatomic,copy)設置NSString屬性的實例。什麼時候會使用副本而不是保留?這是否可以在不影響現有數據的情況下製作獨特的副本?NSString @property,使用複製而不是保留

+2

建議使用副本作爲具有可變/不可變對的類集羣的一部分;例如`NSString` /`NSMutableString`` NSArray``` NSMutableArray`` NSDictionary``` NSMutableDictionary`` NSSet` /`NSMutableSet`,see @ Abizern's answer [here](http://stackoverflow.com/questions/4995254 /的NSMutableString-AS-保留拷貝)。 – Kjuly 2011-12-30 14:43:23

回答

38

是的,它可以在不影響現有數據的情況下製作獨特的副本。合成的setter方法基本上是這樣的:

// For @synthesize(nonatomic, retain) foo: 
- (void) setFoo(NSFoo *theFoo) 
{ 
    [theFoo retain]; // retain new value 
    [foo release]; // release old value, if any 
    foo = theFoo;  // assign new value 
} 

// For @synthesize(nonatomic, copy) foo: 
- (void) setFoo(NSFoo *theFoo) 
{ 
    NSFoo* newFoo = [theFoo copy]; // make copy 
    [foo release]; // release old value, if any 
    foo = newFoo; // assign new value 
} 

注意這裏的操作順序是非常重要的 - 新值必須保留/複製發佈的舊值之前,在自賦值的情況。如果您先釋放,然後將該屬性分配給自己,則可能會意外釋放該值。還請注意,如果舊值爲nil,則發送它release消息是可以的,因爲向nil對象發送消息是明確允許的並且不執行任何操作。

保留與複製的選擇只是決定對象的屬性是否與您設置的值相同。請看下面的代碼:

// suppose the 'foo' property is declared 'retain' and the 'bar' property is 
// declared 'copy' 
NSFoo *foo = ...; 
NSBar *bar = ...; 
someObject.foo = foo; 
someObject.bar = bar; 
[foo changeInternalState]; // someObject.foo also changes, since it's the same object 
[bar changeInternalState]; // someObject.bar does NOT change, since it's a copy 
+0

最後一行可能有拼寫錯誤。 其中//someObject.foo不...應該是//someObject.bar不是 – 2010-02-04 00:59:29

+0

爲了能夠在自定義Class對象上調用`copy`,你必須重寫`copyWithZone:`方法。 – thesummersign 2012-02-02 14:14:57

3

記得有一個NS 易變字符串。如果能夠改變某個其他對象所擁有的字符串的內容(比如刪除其中一半的字符),這將是非常糟糕的,特別是如果您沒有意識到您正在影響另一個對象。因此,對另一個對象製作自己的副本很好。

你可能會說:「好吧,爲什麼我不把它複製到字符串之前?」。也許對象想要一個可變字符串,而你的是不可變的。如果您必須先複製字符串,那麼您必須在其文檔或標題中查找想要的字符串類型,然後製作正確的副本(每次)。這樣,你只需要說other.string = myString,它可以製作任何想要的副本 - 你不必擔心。

0

(出於某種原因,這個帖子出現上述後續問題,我想回答) 回覆:

你的意思是我有釋放之前複製「的 富」對象 'foo'??但是最新的問題,如果我 relaese'foo'複製' foo'??因爲他們是兩個不同的 對象我不明白爲什麼 釋放一個影響其他!

大多數情況下,你是對的。如果它們實際上是兩個獨立的對象,那麼它並不重要。問題在於你將同一個對象分配給自己的可能性。如果你想說

[myObject setFoo: moof]; 
[myObject setFoo: moof]; 

然後第二次你做到了,你會在複製之前釋放moof。在干預的時刻,如果moof的保留數量爲零,那麼moof可能會被刪除,並且在下一步中您將無法複製。 Foo現在是零。

這是否可能發生?可能比你想象的要多。例如,當然用戶可以兩次點擊「更新」按鈕。

我希望這是可以理解和有幫助的。

相關問題