Как копия и 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
65
задан Josh Caswell 4 November 2017 в 14:15
поделиться

4 ответа

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

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

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

72
ответ дан 24 November 2019 в 15:29
поделиться

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

.
3
ответ дан 24 November 2019 в 15:29
поделиться

Я думаю, что вы, должно быть, неправильно поняли, как работает копирование и mutableCopy. В вашем первом примере myArray является неизменяемой копией myArray. Сделав копию, вы можете манипулировать содержимым оригинального myArray и не влиять на содержимое myArray.

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

Если я изменю первый пример, чтобы попытаться вставить/удалить объекты с myArray, то получится неудачно, как и следовало ожидать.


Возможно, поможет подумать о типичном примере использования. Часто бывает так, что можно написать метод, который принимает параметр NSArray *, и в основном сохраняет его для последующего использования. Вы могли бы сделать это так:

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

...но тогда у Вас возникнет проблема, что метод может быть вызван с NSMutableArray в качестве аргумента. Код, который создал массив, может манипулировать им между вызовом метода doStuffLaterWith: и последующим использованием значения. В многопоточном приложении содержимое массива может быть даже изменено во время итерации над ним , что может привести к некоторым интересным ошибкам.

Если вместо этого сделать так:

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

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

8
ответ дан 24 November 2019 в 15:29
поделиться

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

Отредактировано, чтобы удалить мое ошибочное предположение о копировании изменяемых объектов

5
ответ дан 24 November 2019 в 15:29
поделиться
Другие вопросы по тегам:

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