Как применить 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 

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. 

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

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

Interesting Posts

Как пакеты IP-ответа достигают своего адресата внутри частной локальной сети?

Ошибка установки Notepad ++: установка плагина не выполнена

Селектор CSS для первого элемента с classом

ImageField перезаписывает файл с тем же именем

Как пользователи / разработчики могут установить конфигурацию прокси-сервера Android для версий 2.x?

Symfony2: Как получить ошибки проверки формы после привязки запроса к форме

Быстрый способ нахождения строк в одном файле, которые не находятся в другом?

Как сказать Maven игнорировать ошибки SSL (и доверять всем сертификатам)?

Тайм-аут аутентификации форм против сеанса

Как я могу запросить пользователя для подтверждения в сценарии bash?

Неверная операция поперечного streamа: Control ‘textBox1’, доступ к которому осуществляется из streamа, отличного от streamа, который был создан на

Объявление примитивов / объектов, значения инициализации по умолчанию

Окна 7 часов прыгают назад каждый час + интернет-разъединения

android – получить текст из webview

Как использовать Notification.Builder

Давайте будем гением компьютера.