Как применить copy и mutableCopy к NSArray и NSMutableArray?
В чем разница между copy
и mutableCopy
при использовании в NSArray
или NSMutableArray
?
Это мое понимание; это правильно?
// ** 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
- NSMutableArray addObject: - : непризнанный селектор, отправленный экземпляру
- Нюансы NSMutableArray initWithCapacity
- Поиск пересечения NSMutableArrays
- NSMutableArray addObject не влияет на счет?
- NSMutableArray - заставить массив удерживать только определенный тип объекта
- Как я могу получить исходный порядок NSDictionary / NSMutableDictionary?
- NSMutableArray addObject не работает
- Как отсортировать NSMutableArray с пользовательскими объектами в нем?
- 2D-массивы с использованием NSMutableArray
- Невозможно добавить элементы в NSMutableArray ivar
- Как я смогу удалить объекты из NSMutableArray?
- Словарь в Swift с Mutable Array как значение работает очень медленно? Как оптимизировать или построить правильно?
- Как отсортировать NSMutableArray с помощью sortedArrayUsingDescriptors?
copy
и mutableCopy
определяются в разных протоколах ( NSCopying
и NSMutableCopying
, соответственно), а NSArray
соответствует обоим. mutableCopy
определен для NSArray
(а не только для NSMutableArray
) и позволяет вам сделать изменчивую копию первоначально неизменяемого массива:
// 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"];
Резюме:
- вы можете зависеть от результата изменения
mutableCopy
, независимо от исходного типа. В случае массивов результатом должен бытьNSMutableArray
. - вы не можете зависеть от результата
copy
!copy
NSMutableArray
может вернутьNSMutableArray
, так как это исходный class, ноcopy
любого произвольного экземпляраNSArray
не будет.
Изменить: перечитайте исходный код в ответ на ответ Марка Бесси. Когда вы создаете копию своего массива, вы, конечно, можете изменить оригинал независимо от того, что вы делаете с копией. copy
vs mutableCopy
влияет на изменчивость нового массива .
Изменить 2: Исправлено мое (ложное) предположение, что NSMutableArray -copy
вернет NSMutableArray
.
Я думаю, вы, должно быть, неверно истолковали, как работают копирование и mutableCopy. В вашем первом примере myArray_COPY является неизменной копией myArray. Сделав копию, вы можете манипулировать содержимым исходного myArray и не влиять на содержимое myArray_COPY.
Во втором примере вы создаете изменчивую копию myArray, что означает, что вы можете изменить любую копию массива, не затрагивая другую.
Если я изменил первый пример, чтобы попытаться вставить / удалить объекты из myArray_COPY, он терпит неудачу, как и следовало ожидать.
Возможно, подумать о типичном случае использования. Часто бывает, что вы можете написать метод, который принимает параметр NSArray *
, и в основном сохраняет его для последующего использования. Вы можете сделать это следующим образом:
- (void) doStuffLaterWith: (NSArray *) objects { myObjects=[objects retain]; }
… но тогда у вас есть проблема, что метод можно вызвать с помощью NSMutableArray в качестве аргумента. Код, создавший массив, может манипулировать им между тем, когда вызывается метод doStuffLaterWith:, и когда вам нужно будет использовать значение. В многопоточном приложении содержимое массива может быть даже изменено во время повтора по нему , что может вызвать некоторые интересные ошибки.
Если вы сделаете это:
- (void) doStuffLaterWith: (NSArray *) objects { myObjects=[objects copy]; }
Затем копия создает моментальный снимок содержимого массива во время вызова метода.
Метод «copy» возвращает объект, созданный путем реализации протоколов NSCopying copyWithZone:
Если вы отправляете сообщение NSString с копией:
NSString* myString; NSString* newString = [myString copy];
Возвращаемым значением будет NSString (не изменяемый)
Метод mutableCopy возвращает объект, созданный с помощью mutableCopyWithZone протокола NSMutableCopying:
Посылая:
NSString* myString; NSMutableString* newString = [myString mutableCopy];
Возвращаемое значение будет изменчивым.
Во всех случаях объект должен реализовать протокол, означающий, что он создаст новый объект копирования и вернет его вам.
В случае NSArray существует дополнительный уровень сложности в отношении мелкого и глубокого копирования.
Неглубокая копия NSArray копирует только ссылки на объекты исходного массива и помещает их в новый массив.
В результате:
NSArray* myArray; NSMutableArray* anotherArray = [myArray mutableCopy]; [[anotherArray objectAtIndex:0] doSomething];
Будет также влиять на объект с индексом 0 в исходном массиве.
Глубокая копия фактически скопирует отдельные объекты, содержащиеся в массиве. Это делается путем отправки каждому отдельному объекту сообщения «copyWithZone:».
NSArray* myArray; NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray copyItems:YES];
Отредактировано для удаления моего неправильного предположения о копировании изменяемого объекта
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray copyItems:YES];
создаст anotherArray
который является копией oldArray
на 2 уровня в глубину. Если объектом oldArray
является массив. Как правило, это относится к большинству приложений.
Ну, если нам нужна True Deep Copy, которую мы могли бы использовать,
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject: oldArray]];
Это обеспечило бы скопирование всех уровней, сохраняя изменчивость исходного объекта на каждом уровне.
Роберт Кларенс Д’Алмейда, Бангалор, Индия.
Вы вызываете addObject и removeObjectAtIndex в исходном массиве, а не в новую его копию. Вызов copy vs mutableCopy влияет только на изменчивость новой копии объекта, а не на оригинальный объект.
Чтобы сказать это просто,
- copy возвращает неизменяемую (не может быть изменена) копию массива,
- mutableCopy возвращает измененную (может быть изменена) копию массива.
Копировать (в обоих случаях) означает, что вы получаете новый массив, «заполненный» объектными ссылками на исходный массив (т.е. те же (оригинальные) объекты ссылаются на копии.
Если вы добавляете новые объекты в mutableCopy, то они уникальны для mutableCopy. Если вы удаляете объекты из mutableCopy, они удаляются из исходного массива.
Вспомните копию в обоих случаях, как моментальный снимок во время исходного массива на момент создания копии.
Предполагать
NSArray *A = xxx; // A with three NSDictionary objects NSMutableArray *B = [A mutableCopy];
B является объектом NSDictionary, а не NSMutableDictionary, правильно?
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.
Вы должны знать тип возврата этих копирующих материалов, а при объявлении нового объекта, которому будет присвоено, возвращаемое значение должно быть неизменным или изменчивым, иначе компилятор покажет вам ошибку.
Объект, который был скопирован, не может быть изменен с использованием нового, теперь они полностью представляют собой два разных объекта.