Jak stosować copy i mutableCopy do NSArray i NSMutableArray?

Jaka jest różnica między copy i mutableCopy w przypadku stosowania na NSArray lub NSMutableArray?

To jest moje zrozumienie; czy jest poprawne?

// ** NSArray **
NSArray *myArray_imu = [NSArray  arrayWithObjects:@"abc", @"def", nil];

// No copy, increments retain count, result is immutable
NSArray *myArray_imuCopy = [myArray_imu copy];

// Copys object, result is mutable 
NSArray *myArray_imuMuta = [myArray_imu mutableCopy];

// Both must be released later

// ** NSMutableArray **
NSMutableArray *myArray_mut = [NSMutableArray arrayWithObjects:@"A", @"B", nil];

// Copys object, result is immutable
NSMutableArray *myArray_mutCopy = [myArray_mut copy];

// Copys object, result is mutable
NSMutableArray *myArray_mutMuta = [myArray_mut mutableCopy];

// Both must be released later
Author: Josh Caswell, 2010-01-04

8 answers

copy i mutableCopy są zdefiniowane w różnych protokołach (odpowiednioNSCopying i NSMutableCopying), a NSArray są zgodne z obydwoma. mutableCopy jest zdefiniowana dla NSArray (nie tylko NSMutableArray) i pozwala na tworzenie mutowalnej kopii oryginalnie niezmiennej tablicy:

// create an immutable array
NSArray *arr = [NSArray arrayWithObjects: @"one", @"two", @"three", nil ];

// create a mutable copy, and mutate it
NSMutableArray *mut = [arr mutableCopy];
[mut removeObject: @"one"];

Podsumowanie:

  • możesz zależeć od wyniku mutableCopy, aby był zmienny, niezależnie od oryginalnego typu. W przypadku tablic wynikiem powinno być NSMutableArray.
  • ty nie możesz zależeć od wyniku copy być mutable! copying an NSMutableArray Może zwrócić NSMutableArray, ponieważ jest to oryginalna Klasa, ale copykażda Dowolna instancja NSArray tego nie zrobi.

Edit: przeczytaj ponownie oryginalny kod w świetle odpowiedzi Marka Bessey ' a. Podczas tworzenia kopii tablicy, oczywiście możesz nadal modyfikować oryginał, niezależnie od tego, co zrobisz z kopią. copy vs mutableCopy wpływa na to, czy nowa tablica jest zmienna.

Edit 2: Naprawiono moje (fałszywe) założenie że NSMutableArray -copy zwróci NSMutableArray.

 71
Author: Asher Dunn,
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
2010-01-06 19:26:28

Myślę, że musiałeś źle zinterpretować jak działa copy i mutableCopy. W pierwszym przykładzie myArray_COPY jest niezmienną kopią myArray. Po wykonaniu kopii można manipulować zawartością oryginalnego myArray i nie wpływać na zawartość myArray_COPY.

W drugim przykładzie tworzysz zmienną kopię tablicy myArray, co oznacza, że możesz zmodyfikować jedną kopię tablicy, nie wpływając na drugą.

Jeśli zmienię pierwszy przykład, aby spróbować wstawić / usunąć obiekty z myArray_COPY, to nie, tak jak można się spodziewać.


Być może myślenie o typowym przypadku użycia pomogłoby. Często zdarza się, że można napisać metodę, która pobiera parametr NSArray * i zasadniczo przechowuje go do późniejszego użycia. Można to zrobić w ten sposób:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects retain];
}

...ale wtedy masz problem, że metoda może być wywołana z nsmutablearray jako argumentem. Kod, który utworzył tablicę, może nią manipulować, gdy metoda doStuffLaterWith: jest wywołane, a kiedy później trzeba użyć wartości. W aplikacji wielowątkowej zawartość tablicy może zostać zmieniona podczas iteracji , co może spowodować kilka interesujących błędów.

Jeśli zamiast tego zrobisz to:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects copy];
}

..wtedy Kopia wytworzy migawkę zawartości tablicy w momencie wywołania metody.

 8
Author: Mark Bessey,
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
2010-01-04 21:28:02

Metoda "copy" zwraca obiekt utworzony przez implementację nscopying protocols copyWithZone:

Jeśli wyślesz NSString wiadomość kopiującą:

NSString* myString;

NSString* newString = [myString copy];

Wartością zwracaną będzie NSString (nie zmienny)


Metoda mutableCopy zwraca obiekt utworzony przez implementację protokołu nsmutablecopy ' s mutableCopyWithZone:

Wysyłając:

NSString* myString;

NSMutableString* newString = [myString mutableCopy];

Wartość zwracana będzie zmienna.


We wszystkich przypadkach obiekt musi zaimplementować protokół, oznaczając go, utworzy nowy obiekt copy i zwróci go tobie.


W przypadku NSArray istnieje dodatkowy poziom złożoności dotyczący płytkiego i głębokiego kopiowania.

Płytka Kopia NSArray skopiuje tylko odwołania do obiektów oryginalnej tablicy i umieści je w nowej tablicy.

Wynik jest taki, że:

NSArray* myArray;

NSMutableArray* anotherArray = [myArray mutableCopy];

[[anotherArray objectAtIndex:0] doSomething];

Wpłynie również na obiekt o indeksie 0 w oryginalnej tablicy.


Głęboka kopia będzie rzeczywiście kopiuje poszczególne obiekty zawarte w tablicy. Odbywa się to poprzez wysłanie każdemu obiektowi wiadomości" copyWithZone:".

NSArray* myArray;

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
                                                       copyItems:YES];

Edytowano, aby usunąć moje błędne założenie o kopiowaniu obiektów mutowalnych

 5
Author: Corey Floyd,
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
2010-01-06 06:30:46
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

Utworzy anotherArray, która jest kopią oldArray do 2 poziomów głębokich. Jeśli obiekt oldArray jest tablicą. Co zwykle ma miejsce w większości zastosowań.

Cóż, jeśli potrzebujemy prawdziwej głębokiej kopii możemy użyć,

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
    [NSKeyedArchiver archivedDataWithRootObject: oldArray]];

Zapewniłoby to, że wszystkie poziomy są faktycznie kopiowane, zachowując zmienność oryginalnego obiektu na każdym poziomie.

Robert Clarence D ' Almeida, Bangalore, Indie.
 5
Author: robertt almeida,
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
2011-12-30 16:38:51

Wywołujesz addObject i removeObjectAtIndex na oryginalnej tablicy, a nie na jej nowej kopii. Wywołanie copy vs mutableCopy powoduje zmianę tylko nowej kopii obiektu, a nie oryginalnego obiektu.

 3
Author: Dewayne Christensen,
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
2010-01-04 22:56:23

Mówiąc wprost,

  • copy zwraca niezmienną (nie można modyfikować) kopię tablicy,
  • mutableCopy zwraca zmienną (można modyfikować) kopię tablicy.

Kopia (w obu przypadkach) oznacza, że otrzymasz nową tablicę "wypełnioną" referencjami do oryginalnej tablicy (tzn. te same (oryginalne) obiekty są odwołane w kopiach.

Jeśli dodasz nowe obiekty do kopii mutableCopy, to są one unikalne dla kopii mutableCopy. Jeśli usuniesz obiekty z kopii mutableCopy są one usuwane z oryginalnej tablicy.

Pomyśl o kopii w obu przypadkach, jak o migawce w czasie oryginalnej tablicy w czasie tworzenia kopii.

 2
Author: Wizkid,
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
2014-07-05 12:21:45

Załóżmy

NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy]; 

Zawartość B jest obiektem NSDictionary, a nie NSMutableDictionary, prawda?

 0
Author: ZYiOS,
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
2011-05-12 04:28:36
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

Musisz znać typ zwracanych rzeczy i deklarując nowy obiekt, któremu zostanie przypisany, zwracana wartość musi być niezmienna lub zmienna, w przeciwnym razie kompilator pokaże Ci błąd.

Obiekt, który został skopiowany nie może być modyfikowany za pomocą nowego, Są to teraz zupełnie dwa różne obiekty.

 0
Author: Sauvik Dolui,
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
2014-02-19 09:13:27