Между чем различие 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
копирование
и 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
.
Вы вызываете addObject и removeObjectAtIndex на исходном массиве, а не новую его копию. Вызов copy vs mutableCopy влияет только на мутируемость новой копии объекта, а не оригинального объекта.
.Я думаю, что вы, должно быть, неправильно поняли, как работает копирование и mutableCopy. В вашем первом примере myArray является неизменяемой копией myArray. Сделав копию, вы можете манипулировать содержимым оригинального myArray и не влиять на содержимое myArray.
Во втором примере вы создаете мутируемую копию myArray, что означает, что вы можете изменять любую из копий массива, не затрагивая другую.
Если я изменю первый пример, чтобы попытаться вставить/удалить объекты с myArray, то получится неудачно, как и следовало ожидать.
Возможно, поможет подумать о типичном примере использования. Часто бывает так, что можно написать метод, который принимает параметр 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];
Отредактировано, чтобы удалить мое ошибочное предположение о копировании изменяемых объектов