Вопрос

В чем разница между 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
Это было полезно?

Решение

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.

Другие советы

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

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

Метод «copy» возвращает объект, созданный путем реализации протоколов NSCoping 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 представляет собой массив.Что обычно и происходит в большинстве приложений.

Ну, если нам понадобится Настоящая глубокая копия мы могли бы использовать,

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.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top