2013-02-13 11 views
19

popełniłem błąd podczas tworzenia Tableview class, i przypadkowo dotrzymałem @property jak copy kiedy określono go:Dlaczego właściwość NSMutableArray (copy, nonatomic) tworzy NSArrays?

@property (copy, nonatomic) NSMutableArray *words; 

ja zainicjowane tablicę „poprawnie” (Uwaga: jest to trzecia próba, więc proszę ignorować fakt, że nie używam mutableCopy oraz inne lepsze sposoby robienia tego)

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

jednak kiedy później przyszedł, aby zmienić kolejność tablicę, rozbił się na linii removeObjectAtIndex:

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

Z komunikatu o błędzie

unrecognized selector sent to instance 

było dużo kopania, aby dowiedzieć się, że to dlatego, że kopia oznacza, że ​​przypisanie wyników NSMutableArray w tworzeniu standardu (nonmutable) NSArray. Czy ktoś może wyjaśnić, dlaczego to jest prawidłowe zachowanie?

+1

'@property (kopia, nonatomic) NSMutableArray * słowa;' bez użycia kopii, ty shuld use keep. –

+0

lub mocny zamiast zachować –

+1

możliwy duplikat [Używanie -mutableCopyWithZone: na niestandardowej klasie czyni go niezmiennym] (http://stackoverflow.com/questions/14841130/using-mutablecopywithzone-on-custom-class-makes-it-immutable) –

Odpowiedz

31

-kopia, zaimplementowana przez zmienne klasy kakao, zawsze returns their immutable counterparts. Tak więc, gdy NSMutableArray jest wysyłany -copy, zwraca NSArray zawierający te same obiekty.

Ponieważ words ma kwalifikator pamięci copy, ta linia:

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

Rozwija się:

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

Zważywszy, że NSMutableArray jest podklasą NSArray, kompilator nie skarżą, i teraz masz na ręce tykanie bomby zegarowej, ponieważ NSArray nie rozpoznaje tej zmiennej podklasy metod (ponieważ nie może zmutować jej zawartości).

+4

Aby było jasne: 'kopia' dzieje się w syntezowanej implementacji ustawiacza, a nie na stronie wywołania. – bbum

+0

Właśnie poprawiłem moją odpowiedź, aby lepiej zilustrować punkt bbumowy. – macserv

+1

@bbum Oczywiście. To tylko ze względu na zwięzłość. Naprawdę nie chciałem się dowiedzieć, jakie właściwości faktycznie były dla tego rodzaju pytania :) – CodaFi

7

Właściwości nie są magiczne, są tylko skrótem. Deklaracja obiektu @property dla obiektu powoduje, że kompilator tworzy dla niego instancyjną zmienną instancji i metody dostępu. Rzeczywisty wygenerowany kod zależy od atrybutów ustawionych w nieruchomości.

Należy pamiętać, że ustawienie właściwości za pomocą składni kropkowej jest również skrótem. Podczas rozmowy telefonicznej ...

self.words = mutWords; 

... jesteś rzeczywiście powołując wygenerowany accessor metodę za kulisami, jak to:

[self setWords:mutWords]; 

Ponieważ określony atrybut copy na nieruchomości, już powiedziano nam, że kompilator do wygenerowania tej metody -setWords: dostępowej z kodem, który wygląda mniej więcej tak:

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

Wiedząc to wszystko, można zobaczyć, co jest happeni ng: wygenerowana metoda ustawiająca wywoła -copy dla argumentu wejściowego i przypisze wynik do zmiennej instancji kopii. Ponieważ metoda -copy jest zawsze zaimplementowana w celu zwrócenia obiektu niezmiennego (wykonanie [aMutableString copy] zwróci wartość NSString itd.), Ta właściwość zawsze będzie przechowywać niezmienną kopię.

Powiązane problemy