Как 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
64 голоса | спросил fuzzygoat 4 Jpm1000000pmMon, 04 Jan 2010 23:56:33 +030010 2010, 23:56:33

8 ответов


0

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, поскольку это оригинальный класс, но copy любой произвольный экземпляр NSArray не будет.

Изменить. перечитайте исходный код в свете ответа Марка Бесси. Когда вы создаете копию массива, вы, конечно, можете изменить оригинал независимо от того, что вы делаете с копией. copy против mutableCopy влияет на то, новый массив является изменяемым.

Изменить 2 . Исправлено мое (ложное) предположение о том, что NSMutableArray -copy вернет NSMutableArray

ответил Asher Dunn 5 Jam1000000amTue, 05 Jan 2010 00:11:06 +030010 2010, 00:11:06
0

Я думаю, вы неправильно поняли, как работают copy и 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];
}

.. затем копия создает снимок содержимого массива во время вызова метода.

ответил Mark Bessey 5 Jam1000000amTue, 05 Jan 2010 00:12:32 +030010 2010, 00:12:32
0

Метод "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];

Отредактировано для удаления моего неверного предположения о копировании изменяемого объекта

ответил Corey Floyd 5 Jam1000000amTue, 05 Jan 2010 00:25:47 +030010 2010, 00:25:47
0
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray
                                                           copyItems:YES];

создаст anotherArray, который является копией oldArray до 2 уровня. Если объект oldArray является массивом. Что обычно имеет место в большинстве приложений.

Ну, если нам понадобится True Deep Copy , которую мы могли бы использовать,

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

Это обеспечит копирование всех уровней, сохраняя изменчивость исходного объекта на каждом уровне.

Роберт Кларенс д'Альмейда, Бангалор, Индия.

ответил robertt almeida 2 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 02 Sep 2011 20:06:54 +0400 2011, 20:06:54
0

Вы вызываете addObject и removeObjectAtIndex для исходного массива, а не для новой копии, которую вы сделали. Вызов copy против mutableCopy влияет только на изменчивость новой копии объекта, а не исходного объекта.

ответил Dewayne Christensen 5 Jam1000000amTue, 05 Jan 2010 01:56:23 +030010 2010, 01:56:23
0

Проще говоря,

  • copy возвращает неизменную (не может быть изменена) копию массива,
  • mutableCopy возвращает изменяемую (может быть измененную) копию массива.

Копирование (в обоих случаях) означает, что вы получаете новый массив, «заполненный» ссылками на исходный массив (то есть те же (оригинальные) объекты, на которые есть ссылки в копиях.

Если вы добавляете новые объекты в mutableCopy, они уникальны для mutableCopy. Если вы удаляете объекты из mutableCopy, они удаляются из исходного массива.

Представьте себе копию в обоих случаях как моментальный снимок исходного массива на момент создания копии.

ответил Wizkid 5 J000000Saturday14 2014, 15:57:02
0

Предположим,

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

B - это объект NSDictionary, а не NSMutableDictionary, верно?

ответил ZYiOS 12 Mayam11 2011, 08:28:36
0
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

Вы должны знать тип возврата этих копируемых материалов, и при объявлении нового объекта, которому будет присвоен объект, возвращаемое значение должно быть неизменным или изменяемым, в противном случае компилятор покажет вам ошибку.

Скопированный объект нельзя изменить с помощью нового, теперь это два совершенно разных объекта.

ответил Sauvik Dolui 7 AM000000100000003031 2013, 10:28:30

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132