2

I have an NSMutableArray of custom objects (based on NSObject) which I want to copy into a new array. But I want it to be a deep copy.

How do I go about doing this? Do I need to implement the NSCopying protocol in my custom object?

Thanks

Alex Stuckey
  • 1,250
  • 1
  • 14
  • 28

2 Answers2

5

Yes, you need to indicate that your custom class adheres to the NSCopying protocol and then you implement the copyWithZone: method. This allows your class to be copied. In your implementation of copyWithZone: you need to decide how much of the internals also need deep copying.

Now if you do a deep copy of the array, the new array will include copied versions of your object and not just references to the originals.

Please note that a regular copy of an array doesn't do a deep copy. To make a deep copy you want something like:

NSArray *deepCopyArray=[[NSArray alloc] initWithArray:someArray copyItems:YES];
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • No, calling copy on an array will not make a deep copy, no matter what protocol the contained elements implement – Eiko Oct 30 '12 at 00:15
  • @Eiko I never said calling `copy` on an array will make a deep copy. I stated how to ensure the custom object is copyable. I then mentioned that if a deep copy of the array is made... – rmaddy Oct 30 '12 at 00:17
  • 1
    @maddy Hmm ok, I think "Now if you do a deep copy of the array, ..." is easy to misunderstand, then. – Eiko Oct 30 '12 at 00:19
  • So how does one go about deep copying? Is it part of these classes or does it need to be implemented in a category as I have seen on the web? – Alex Stuckey Oct 30 '12 at 00:27
  • @Eiko Give me a minute to make a change before you edit my answer. – rmaddy Oct 30 '12 at 00:30
  • Thanks, I altered my code to create a new array from another (as in your example) rather than NSMutableArray *newArray = [oldarray copy]. I also implemented the NSCopying protocol in my own classes – Alex Stuckey Oct 30 '12 at 00:41
1

Deep copying an array can be done by going through all elements manually. This is necessary if the objects require further deep copying.

NSMutableArray *deepCopied = [NSMutableArray arrayWithCapacity:[array count]];

// assumes your objects know how to "deepCopy"    
for (id object in array)
{
    // if not ARC or GC:
    [deepCopied addObject:[[object deepCopy] aurorelease]];

    // if ARC or GC
    [deepCopied addObject:[object deepCopy]];
}

Otherwise:

NSArray *deepCopied = [[NSArray alloc] initWithArray:array copyItems:YES];

There is a category method described in an answer here that may help if you need to make a lot of deep copies.

Community
  • 1
  • 1
dreamlax
  • 93,976
  • 29
  • 161
  • 209