2010-01-04 3 views
60

В чем разница между copy и mutableCopy при использовании на NSArray или NSMutableArray?Как скопировать и 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 
+1

У вас есть ошибка в вашем редактировании; уверен, что это опечатка или недоразумение. В первом блоке кода переменная myArray_imuMuta, назначенная с помощью mutableCopy, * mutable *, не является неизменной, как указывает ваш комментарий. –

+0

Спасибо, это была ошибка, я запутался в Xcode, сказав: «Предупреждение NSArray может не отвечать на add -addObject/-removeObjectAtIndex. Я изменю myArray_imuMuta на NSMutableArray. – fuzzygoat

+0

@JamesHarnett - пожалуйста, прекратите редактирование на имя" Совместимость с ARC "- см. [Этот мета-пост] (http://meta.stackoverflow.com/questions/268309/is-it-okay-to-convert-non-arc-objective-c-answers-to-arc) для почему. – Krease

ответ

64

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 ing NSMutableArrayмай возвращение NSMutableArray, так как это первоначальный класс, но copy ing любой произвольный NSArray экземпляр не будет.

Edit: перечитайте свой исходный код в свете ответа Mark Bessey в. Когда вы создаете копию своего массива, вы, конечно, можете изменить оригинал независимо от того, что вы делаете с копией. copy vs mutableCopy влияет на то, изменен ли новый массив .

Edit 2: Fixed мой (ложное) предположение о том, что NSMutableArray -copy будет возвращать NSMutableArray.

+3

Отправка -copy в NSMutableArray обычно не возвращает другой изменчивый массив. Конечно, он мог бы сделать это *, но в обычном случае он возвращает неизменный массив с постоянным временем доступа. –

+0

К сожалению, вы правы. Я неправильно читал код OP и думал, что он модифицировал результат -copy. Было бы так же полезно, чтобы NcoputableArray -copy возвращал другой изменяемый массив, поэтому я (неправильно) предположил, что это так. –

+0

Я что-то пропустил Я не найти ссылки на [mut remove: @ "one"]; если это не будет [mut removeObjectIdenticalTo: @ "one"]; Я просто хочу уточнить, кто читает это и пытается учиться? – fuzzygoat

8

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

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

6

Метод «копия» возвращает объект, созданный путем реализации 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]; 

Edited удалить мое ошибочное предположение о изменяемый объект копирования

3

Вы звоните AddObject и removeObjectAtIndex на исходном массиве, а не новую копию этого вы сделали. Вызов copy vs mutableCopy влияет только на изменчивость новой копии объекта, а не на оригинальный объект.

0

Пусть содержание

NSArray *A = xxx; // A with three NSDictionary objects 
NSMutableArray *B = [A mutableCopy]; 

B является NSDictionary не объект NSMutableDictionary, правильно ли это?

5
NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:oldArray 
                  copyItems:YES]; 

создаст anotherArray, который является копией oldArray до 2 уровня вложенности. Если объект oldArray является массивом. Как правило, это относится к большинству приложений.

Ну, если нам нужно Истинной Deep Copy мы могли бы использовать,

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: 
    [NSKeyedArchiver archivedDataWithRootObject: oldArray]]; 

Это будет гарантировать, что все уровни фактически скопированы сохранению переменчивости исходного объекта на каждом уровне.

Robert Clarence D'Almeida, Бангалор, Индия.

+0

Ваша концепция «True Deep Copy» Действительно хорошая. Именно то, что я хочу ... Большое спасибо и +1 за вас ..... –

0
-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it. 

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

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

2

Для ее просто,

  • копия возвращает неизменный (не может быть изменена) копию массива,
  • mutableCopy возвращает изменяемый (может быть изменена) копию массива.

Копирование (в обоих случаях) означает, что вы получите новый массив «заселен» с объектные ссылки на исходный массив (то есть одни и те же (оригинальное) объекты ссылаются в копиях.

Если вы добавляете новые объекты в mutableCopy, то они уникальны для mutableCopy.Если вы удаляете объекты из mutableCopy, они удаляются из исходного массива.

Подумайте о копии в обоих случаях, как о снимке во время оригинала массив на момент создания копии.

Смежные вопросы