Как копирование и mutableCopy применяются к NSArray и NSMutableArray?
-
18-09-2019 - |
Вопрос
В чем разница между 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.
Вы должны знать тип возвращаемого значения этих копирующих материалов, и при объявлении нового объекта, которому будет присвоено, возвращаемое значение должно быть неизменяемым или изменяемым, иначе компилятор покажет вам ошибку.
Скопированный объект нельзя изменить с помощью нового, теперь это совершенно два разных объекта.