Dlaczego (kopiująca, nieatomiczna) właściwość NSMutableArray tworzy nsarrays?

Popełniłem błąd podczas tworzenia widoku TableView class i przypadkowo zachowałem @property jako copy Kiedy go zdefiniowałem:

@property (copy, nonatomic) NSMutableArray *words; 

Zainicjalizowałem tablicę "poprawnie": (zauważ, że jest to trzecia próba, więc proszę zignorować fakt, że nie używam mutableCopy i innych lepszych sposobów na to)

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łem zmienić kolejność tablicy, rozbiła się na linii removeObjectAtIndex:

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

Z Komunikatem o błędzie

unrecognized selector sent to instance

Zajęło dużo kopania do dowiedz się, że dzieje się tak, ponieważ kopia oznacza, że przypisanie NSMutableArray powoduje utworzenie standardowego (niemutable) NSArray. Czy ktoś może wyjaśnić, dlaczego jest to prawidłowe zachowanie?

Author: P.J.Radadiya, 2013-02-13

2 answers

- Kopia, zaimplementowana przez zmienne klasy Cocoa, zawsze zwraca ich niezmienne odpowiedniki . Tak więc, gdy wysyłana jest kopia NSMutableArray, zwraca ona NSArray zawierający te same obiekty.

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

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

Rozszerza się do:

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

Biorąc pod uwagę, że NSMutableArray jest podklasą NSArray, kompilator nie narzeka, a Ty masz teraz tykającą bombę na rękach, ponieważ NSArray nie rozpoznaje jest to metoda mutowalna podklasy (ponieważ nie może zmutować jej zawartości).

 33
Author: CodaFi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-13 15:24:50

Właściwości nie są magiczne, są tylko skrótem. Deklaracja @property na Twoim obiekcie mówi kompilatorowi, aby stworzył zmienną instancji pomocniczej i metody dostępu do niej. Rzeczywisty wygenerowany kod zależy od atrybutów ustawionych na właściwości.

Ważne jest, aby pamiętać, że Ustawianie właściwości za pomocą składni kropki jest również skrótem. Kiedy dzwonisz ...

self.words = mutWords;

...wywołujesz wygenerowaną metodę accessor za kulisami, jak to:

[self setWords:mutWords];

Ponieważ podałeś atrybut copy na swojej właściwości, kazałeś kompilatorowi wygenerować metodę -setWords: accessor z kodem, który wygląda mniej więcej tak:

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

Wiedząc to wszystko, możesz zobaczyć, co się dzieje: wygenerowana metoda setter wywoła -copy na argumencie wejściowym i przypisze wynik do zmiennej instancji wspierającej. Ponieważ metoda -copy jest zawsze zaimplementowana w celu zwrócenia obiektu niemutowalnego (wykonanie [aMutableString copy] zwróci NSString, itd.) ustawienie tej właściwości zawsze będzie przechowywać kopię niemutowalną.

 7
Author: macserv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-14 19:14:14