1

I have a question what's the difference between these two methods on initializing an array?

I am assuming copyItems will provide a deep copy?

When would you use one versus the other?

Thank you!

Alan
  • 9,331
  • 14
  • 52
  • 97
  • @trojanfoe thank you for that link. I just read it and it seems like copyItems doesn't do a deep copy. I am curious as to when to use one or the other. I have always been using only `initWithArray` – Alan Nov 20 '13 at 14:43

2 Answers2

4

The documentation for these methods is the first result (for me) with a little Google search.

initWithArray: copyItems:

has this documentation:

Initializes a newly allocated array using anArray as the source of data objects for the array.

Parameters
array
An array containing the objects with which to initialize the new array.

flag
If YES, each object in array receives a copyWithZone: message to create a copy of the object—objects must conform to the NSCopying protocol. In a managed memory environment, this is instead of the retain message the object would otherwise receive. The object copy is then added to the returned array. If NO, then in a managed memory environment each object in array simply receives a retain message when it is added to the returned array.

whereas initWithArray: has this documentation:

Initializes a newly allocated array by placing in it the objects contained in a given array.

e.g. Note: Since NSArray isn't mutable, my corresponding implementations aren't directly usable

 `array2 = [[NSArray alloc] initWithArray:array1 copyItems:YES]`  
 //would correspond to:
 array2 = @[
    [array1[0] copy],
    [array1[1] copy],
    [array1[2] copy],
    ...
    [array1[n] copy],
]

whereas

 array2 = [[NSArray alloc] initWithArray:array1]
 //would correspond to:
 array2 = @[
    array1[0],
    array1[1],
    array1[2],
    ...
    array1[n],
]

//or
array2[0] = array1[0];
array2[1] = array1[1];
array2[2] = array1[2];
...
array2[n] = array1[n];
James Webster
  • 31,873
  • 11
  • 70
  • 114
3

initWithArray: initializes a new array and places in it all the objects contained in a given array. This means that each object in the given array will receive a retain. Hence, if you edit an object in the new array, you will modify that object even in the given array. (see shallow copy)

On the other hand, initWithArray:copyItems:, if YES is passed as second argument, will provide a deep copy.

Beware that if you need to deeply copy an entire nested data structure then this approach will not suffice. (see the Apple documentation)

Example:

NSMutableString *s = [[NSMutableString alloc] initWithString:@"hello"];
NSArray *a = @[s];
NSArray *b = [[NSArray alloc] initWithArray:a];
[a[0] appendString:@" there"];

after these lines the arrays a and b will contain the mutable string "hello there"

NSMutableString *s = [[NSMutableString alloc] initWithString:@"hello"];
NSArray *a = @[s];
NSArray *c = [[NSArray alloc] initWithArray:a copyItems:YES];
[a[0] appendString:@" there"];

while after these lines the array c will contain the mutable string "hello" and the array a will contain the mutable string "hello there"

Luca Torella
  • 7,974
  • 4
  • 38
  • 48
  • Actually in the second example it is exactly the opposite: 'a' will contain "hello there" and 'c' will contain "hello" :) – joakim Nov 19 '14 at 15:45
  • are you sure you read the example correctly? I just run the code and it works asa expected. – Luca Torella Nov 19 '14 at 18:59
  • 2
    I just pasted the second example as-is. 'a' logs "hello there" and 'c' logs "hello" and that's the expected result. 'c' holds a copy i.e. a NEW object entirely. The append only affects the 'original'. https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Collections/Articles/Copying.html – joakim Nov 19 '14 at 19:50
  • Ah yes, sorry I didn't read my description I just read my code. Yes, clearly I inverted them, but the example is doing what I wanted to show. Now I'll fix the answer, thanks – Luca Torella Nov 20 '14 at 07:53