0

I am trying to implement deep and shallow copy for NSMutableArray,

self.oldArray =[[NSMutableArray alloc] initWithCapacity:0];
self.shallowCopy =[[NSMutableArray alloc] initWithCapacity:0];
self.deepCopy =[[NSMutableArray alloc] initWithCapacity:0];


//add object to old Array
[self.oldArray addObject:@"rooban"];
[self.oldArray addObject:@"radha"];
[self.oldArray addObject:@"jesus"];
[self.oldArray addObject:@"god"];


self.shallowCopy=[[NSMutableArray alloc] initWithArray:self.oldArray];
self.deepCopy=[[NSMutableArray alloc] initWithArray:self.oldArray copyItems:YES];

//deep copy
NSLog(@"Lenght of the Old Array before: %d",self.deepCopy.count);
[self.deepCopy removeObject:@"rooban"];
NSLog(@"Lenght of the Old Array After: %d",self.oldArray.count);

//shallow copy
NSLog(@"Lenght of the Old Array Before: %d",self.shallowCopy.count);
[self.shallowCopy removeObject:@"rooban"];
NSLog(@"Lenght of the Old Array After: %d",self.oldArray.count);

the output of this program is,

deep copy :
Lenght of the Old Array before: 4
Lenght of the Old Array After: 4

shallow copy :
Lenght of the Old Array Before: 4
Lenght of the Old Array After: 4

I don't know why shallow copy deletion not reflecting to original NSMutableArray.

Rooban Ponraj A
  • 281
  • 4
  • 20
  • Initializing `deepCopy` and `shallowCopy` in the beginning and then re-assigning them is both wasteful and could possibly be a leak if you are not using ARC. – David Rönnqvist Feb 24 '13 at 09:14

3 Answers3

2

You can understand like this..

NSMutableArray *oldArray =[[NSMutableArray alloc] initWithCapacity:0]; NSMutableArray *shallowCopy; // =[NSMutableArray arrayWithCapacity:0]; NSMutableArray *deepCopy; // =[[NSMutableArray alloc] initWithCapacity:0];

//add object to old Array
[oldArray addObject:@"rooban"];
[oldArray addObject:@"radha"];
[oldArray addObject:@"jesus"];
[oldArray addObject:@"god"];


shallowCopy = oldArray;
deepCopy = [oldArray mutableCopy];

//deep copy
NSLog(@"Lenght of the Old Array before: %d",deepCopy.count);
[deepCopy removeObject:@"rooban"];
NSLog(@"Lenght of the Old Array After: %d",oldArray.count);

//shallow copy
NSLog(@"Lenght of the Old Array Before: %d",shallowCopy.count);
[shallowCopy removeObject:@"rooban"];
NSLog(@"Lenght of the Old Array After: %d",oldArray.count);

Output is:

(-[ViewController viewDidLoad]) (ViewController.m:34) Lenght of the Old Array before: 4 (-[ViewController viewDidLoad]) (ViewController.m:36) Lenght of the Old Array After: 4 (-[ViewController viewDidLoad]) (ViewController.m:39) Lenght of the Old Array Before: 4 (-[ViewController viewDidLoad]) (ViewController.m:41) Lenght of the Old Array After: 3

the concept is for Shallow copy and Deep copy is:

If B is a shallow copy of A, then it is like B = [A assign];

B and A point to the same memory location

If B is a deep copy of A, then it is like B = [A copy];

B and A point to different memory locations

B memory size is same as A's

B has same contents as A's

iOS_User
  • 1,372
  • 5
  • 21
  • 35
1

This happens because initWithArray: is not doing a shallow copy. You are getting a completely new array with pointers to the same objects as the other array.

E.g. if the objects you added were mutable strings you could change one of them and it would be visible in both the new and old array since they point to the same mutable string.

On the other hand, the array created with initWithArray:copyItems: would not be affected by the above change since it points to copies of the objets that were in the original array.

iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
  • can i know how we can implement shallow and deep copy for collection in ios? – Rooban Ponraj A Feb 24 '13 at 10:19
  • @RoobanAbraham Now that I think of it, isn't the behavior you are seeing in your question the behavior of a shallow copy? What you are expecting it to do however is not the behavior of a shallow copy. To get the behavior you are talking about in your question you would just create another pointer to the original array. – David Rönnqvist Feb 24 '13 at 10:41
0

If NSArray/NSDictionary contains JSON Serialisable data then Deep copy can be easily achieved using NSJSONSerialization.

Simply take NSData of NSArray using NSJSONSerialization and then recreate JSON Object, this will create a complete new and fresh copy of NSArray/NSDictionary with new memory references of them.

But make sure the objects of NSArray/NSDictionary and their children must be JSON serializable.

NSData *aDataOfSource = [NSJSONSerialization dataWithJSONObject:oldCopy options:NSJSONWritingPrettyPrinted error:nil];
NSDictionary *aDictNewCopy = [NSJSONSerialization JSONObjectWithData:aDataOfSource options:NSJSONReadingMutableLeaves error:nil];
Mrug
  • 4,963
  • 2
  • 31
  • 53