16

I have read the answer for difference between deep copy and shallow copy from the post, What is the difference between a deep copy and a shallow copy? . Now I got some doubt that when we made a shallow copy by

 newArray = [NSmutableArray arrayWithArray:oldArray];

the new array will point to oldArray. (As from the figure). Now what happen when I remove object from newArray? As from figure, it should remove same element from oldArray too !!! It seems like

newArray = oldArray is a shallow copy and newArray = [NSmutableArray arrayWithArray:oldArray]; is deep copy. Is it right?

Community
  • 1
  • 1
rakeshNS
  • 4,227
  • 4
  • 28
  • 42

4 Answers4

43

newArary = oldArray isn't a copy at all. You end up with two pointers pointing to the exact same memory location.

newArray = [NSMutableArray arrayWithArray:oldArray]; is a shallow copy. You end up with two distinct arrays, so if you were to remove or add items from one array, it wouldn't affect the other array. However, the items in the two arrays are identical. If the first element of oldArray were an NSMutableDictionary and you added a key to it, you'd see that change on the first element of newArray as well (since those two objects are the same).

To do a deep copy, you would have to make a new array, and each element of the new array would be a deep copy of the corresponding element of the old array. (Yes, that definition is recursive).

Kunal Gupta
  • 2,984
  • 31
  • 34
yuji
  • 16,695
  • 4
  • 63
  • 64
  • 1
    According to Apple (https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/ObjectCopying.html), So if object A is shallow-copied to object B, object B refers to the same instance variable (or property) that object A refers to. Hence newArray = [NSMutableArray arrayWithArray:oldArray]; is a deep copy not shallow copy. Please correct me if I am wrong. – Harshit Gupta Jan 13 '16 at 21:25
11

First of all, NSArray's don't have a deep copy function. However, you can make a deep copy function by doing the following:

@interface NSArray(deepCopy)

-(NSArray *) deepCopy;

@end

@implementation

-(NSArray *) deepCopy
{
    NSMutableArray *ret = [NSMutableArray array];

    for (id val in self)
    {
        if ([val conformsToProtocol:@protocol(NSCopying)])
        { 
            [ret addObject:[val copy]];
        }
        else
        {
           [ret addObject:val];
        }
    }

    return ret;
}

@end 

Second of all, newArray = oldArray does not copy the array. It simply makes newArray point to the array that oldArray points to.

Third, +arrayWithArray: does a shallow copy of the array, meaning the individual objects are NOT copied.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • I think you forgot the else around `[ret addObject:val];` – Matthias Bauch Mar 28 '12 at 18:31
  • I think `[ret addObject:[val copy]]` is a memory leak assuming `NSCopying` is adopted according to Apple's docs (`copyWithZone:` returns an object that's implicitly retained by the sender). – SundayMonday Nov 05 '12 at 15:43
  • 1
    Would assume ARC (automatic reference counting) is being used in this case. – trapper Nov 05 '12 at 15:47
  • 1
    [ret addObject:[val copy]]; will copy each element in original array shallow. then if I have an array of arrays using your method (deepcopy) I will end up with a new array with inner arrays shallow copied.which is wrong isn't it. – Ali Amin Jun 06 '13 at 08:04
  • @عليامين no, it isn't "wrong", it's an edge case. If the copy implementation by a custom object doesn't do a deep copy (like it should, there's very little I can do, aside from serializing and deserializing it. – Richard J. Ross III Jun 06 '13 at 13:09
2

You can also call [[NSArray alloc] initWithArray:arraytoBeCopied copyItems:YES];

Genki
  • 3,055
  • 2
  • 29
  • 42
-8

In Objective-C "Copy" keyword just increase the "Retain Count" of the object. So only use of "Copy" will not perform a copy.

But when we make a change in object, then Objective-C create a copy of the original object at that time.

Please correct me if i am wrong.

Thanks

iPhoneBuddy
  • 49
  • 10
  • 1
    I don't think your answer is correct. In fact, I'm reasonably certain it's not. – RonLugge Sep 18 '13 at 17:48
  • You can find it in apple documentation. Thanks. – iPhoneBuddy Sep 19 '13 at 08:54
  • 1
    Really? Because when I look at the documentation, I find that NSObject says that copy is a shortcut for copyWithZone:, which must be implemented by subclasses that wish to enable that function according to the NSCopying protocol. Which specifies that CopyWithZone creates a new object with identical properties -- not an increase in retain count. Furthermore, Apple has explicitly disabled all use of retain count since ARC was added. So saying 'copy' just increases retain count on an object is flat-out wrong, no matter how you cut it. – RonLugge Sep 19 '13 at 19:40
  • https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Collections/Articles/Copying.html#//apple_ref/doc/uid/TP40010162-SW3 – iPhoneBuddy Sep 20 '13 at 06:39
  • 4
    I'm sorry didn't state my position more clearly: I am NOT arguing with your second paragraph. That, as far as I can tell, is correct (though as the documentation you link to points out, it doesn't produce a 'true' deep copy, because it will only go one level deep -- IMO, a flaw). I am arguing *very* specifically with your first paragraph. 'Copy' does, in fact, return a new instance of the class. It's just that the contents of that class are references to the old objects, rather than copies. – RonLugge Sep 21 '13 at 01:19