В чем разница между 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
8 ответов
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
vs 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» возвращает объект, созданный реализацией протоколов 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 влияет только на изменчивость новой копии объекта, но не исходного объекта.
Предполагать
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.
Вы должны знать тип возврата этих копируемых материалов, и при объявлении нового объекта, которому будет назначен объект, возвращаемое значение должно быть неизменным или изменяемым, иначе компилятор покажет вам ошибку.
Скопированный объект не может быть изменен с помощью нового, теперь это два разных объекта.
Проще говоря,
- copy возвращает неизменяемую (не может быть изменена) копию массива,
- mutableCopy возвращает изменяемую (можно изменять) копию массива.
Копирование (в обоих случаях) означает, что вы получаете новый массив, "заполненный" ссылками на объекты исходного массива (т.е. в копиях есть ссылки на одни и те же (исходные) объекты.
Если вы добавляете новые объекты в mutableCopy, они уникальны для mutableCopy. Если вы удалите объекты из mutableCopy, они будут удалены из исходного массива.
Думайте о копии в обоих случаях как о моментальном снимке исходного массива во время создания копии.
Похожие вопросы
Связанные вопросы
Новые вопросы
cocoa
Cocoa - это среда разработки приложений Apple для macOS, состоящая из Foundation, Application Kit и Core Data. Используйте тег «Какао-touch» для вопросов iOS.