2013-02-13 69 views
19

我犯了一個錯誤,同時創造一個TableView中class,並且意外地保持我的@propertycopy當我定義它:爲什麼(複製,非原子)NSMutableArray屬性創建NSArrays?

@property (copy, nonatomic) NSMutableArray *words; 

我初始化數組「正確」(注:這是第三次嘗試,所以請忽略我不是使用mutableCopy及其他更好的這樣做的方法)

NSArray *fixedWords = @[@"Eeny", @"Meeny", @"Miny", @"Moe", @"Catch", @"A", @"Tiger", @"By", @"His", @"Toe"]; 
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; 
self.words = mutWords; 

然而,當我後來重新排序陣列的事實,它墜毀在removeObjectAtIndex行:

id object = [self.words objectAtIndex:fromIndexPath.row]; 
NSUInteger from = fromIndexPath.row; 
NSUInteger to = toIndexPath.row; 
[self.words removeObjectAtIndex:from]; 

隨着錯誤消息

unrecognized selector sent to instance 

採取了很多挖弄清楚,這是因爲該拷貝意味着分配在創建一個標準(nonmutable)的NSArray的NSMutableArray中的結果。任何人都可以解釋爲什麼這是正確的行爲?

+1

'@財產(副本,非原子)的NSMutableArray *字樣;'沒有用的副本,你shuld使用保留。 – 2013-02-13 15:18:04

+0

或強,而不是保留 – 2013-02-13 15:20:25

+1

可能重複[使用-mutableCopyWithZone:在自定義類使它不變(http://stackoverflow.com/questions/14841130/using-mutablecopywithzone-on-custom-class-makes-it-immutable ) – 2013-02-13 15:21:42

回答

31

-copy,由可變Cocoa類實現,始終爲returns their immutable counterparts。因此,當發送一個NSMutableArray時,它返回一個包含相同對象的NSArray。

因爲words具有記憶預選賽copy,這條線:

NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; 
self.words = mutWords; 

擴展出來:

NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; 
self.words = [mutWords copy]; 

因爲NSMutableArray的是NSArray中的一個子類,編譯器不抱怨,和你現在有一個定時炸彈,因爲NSArray不能識別它的可變子類的方法(因爲它不能改變它的內容)。

+4

要明確:'copy'發生在合成實施二傳手,而不是在調用點。 – bbum 2013-02-13 16:59:03

+0

剛剛修改我的回答,以更好地說明bbum的觀點。 – macserv 2013-02-13 17:36:59

+1

@bbum當然。這只是爲了簡潔起見。我真的沒有想進入什麼樣的屬性實際上是對這類問題的:) – CodaFi 2013-02-13 17:47:26

7

屬性並不神奇,它們只是速記。在對象上聲明@property將告知編譯器爲它創建一個支持實例變量和訪問器方法。實際生成的代碼取決於您在屬性上設置的屬性。

請務必記住,使用點語法設置屬性也是一種簡寫。當你呼喚我

self.words = mutWords; 

...你實際上是調用生成的訪問方法在幕後,就像這樣:

[self setWords:mutWords]; 

既然你指定你的財產的copy屬性,你已經告訴編譯器生成的代碼-setWords:訪問方法,看起來是這樣的:

- (void)setWords:(NSMutableArray *)words 
{ 
    _words = [words copy]; 
} 

知道了這一切,你可以看到什麼是happeni ng:生成的setter方法將在輸入參數上調用-copy,並將結果分配給支持實例變量。由於-copy方法總是實現爲返回一個不可變對象(執行[aMutableString copy]將返回一個NSString,等等)設置,該屬性將始終存儲不可變副本。

相關問題