Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 242 Vote(s) - 3.78 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Deep copying an NSArray

#1
Is there any built-in function that allows me to deep copy an `NSMutableArray`?

I looked around, some people say `[aMutableArray copyWithZone:nil]` works as deep copy. But I tried and it seems to be a shallow copy.

Right now I am manually doing the copy with a `for` loop:

//deep copy a 9*9 mutable array to a passed-in reference array

-deepMuCopy : (NSMutableArray*) array
toNewArray : (NSMutableArray*) arrayNew {

[arrayNew removeAllObjects];//ensure it's clean

for (int y = 0; y<9; y++) {
[arrayNew addObject:[NSMutableArray new]];
for (int x = 0; x<9; x++) {
[[arrayNew objectAtIndex:y] addObject:[NSMutableArray new]];

NSMutableArray *aDomain = [[array objectAtIndex:y] objectAtIndex:x];
for (int i = 0; i<[aDomain count]; i++) {

//copy object by object
NSNumber* n = [NSNumber numberWithInt:[[aDomain objectAtIndex:i] intValue]];
[[[arrayNew objectAtIndex:y] objectAtIndex:x] addObject:n];
}
}
}
}

but I'd like a cleaner, more succinct solution.
Reply

#2
No, there isn't something built into the frameworks for this. Cocoa collections support shallow copies (with the `copy` or the `arrayWithArray:` methods) but don't even talk about a deep copy concept.

This is because "deep copy" starts to become difficult to define as the contents of your collections start including your own custom objects. Does "deep copy" mean *every* object in the object graph is a unique reference relative to *every* object in the original object graph?

If there was some hypothetical `NSDeepCopying` protocol, you could set this up and make decisions in all of your objects, but unfortunately there isn't. If you controlled most of the objects in your graph, you could create this protocol yourself and implement it, but you'd need to add a category to the Foundation classes as necessary.

@AndrewGrant's answer suggesting the use of keyed archiving/unarchiving is a nonperformant but correct and clean way of achieving this for arbitrary objects. [This book even goes so far so suggest][1] adding a category to all objects that does exactly that to support deep copying.


[1]:

[To see links please register here]

Reply

#3
## Copy by default gives a shallow copy

That is because calling `copy` is the same as `copyWithZone:NULL` also known as copying with the default zone. The `copy` call does not result in a deep copy. In most cases it would give you a shallow copy, but in any case it depends on the class. For a thorough discussion I recommend the [Collections Programming Topics][1] on the Apple Developer site.

## initWithArray:CopyItems: gives a one-level deep copy
NSArray *deepCopyArray = [[NSArray alloc] initWithArray:someArray copyItems:YES];


## `NSCoding` is the Apple recommended way to provide a deep copy

For a true deep copy (Array of Arrays) you will need `NSCoding` and archive/unarchive the object:

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


[1]:

[To see links please register here]

Reply

#4
I have a workaround if trying to achieve deep copy for JSON compatible data.

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];

Reply

#5
**For Dictonary**

`NSMutableDictionary *newCopyDict = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)objDict, kCFPropertyListMutableContainers);`

**For Array**

`NSMutableArray *myMutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, arrData, kCFPropertyListMutableContainersAndLeaves);`
Reply

#6
The only way I know to easily do this is to archive and then immediately unarchive your array. It feels like a bit of a hack, but is actually explicitly suggested in the [Apple Documentation on copying collections][1], which states:

> If you need a true deep copy, such as when you have an array of arrays, you can archive and then unarchive the collection, provided the contents all conform to the NSCoding protocol. An example of this technique is shown in Listing 3.

> ###Listing 3 A true deep copy

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

The catch is that your object must support the NSCoding interface, since this will be used to store/load the data.

[1]:

[To see links please register here]


##Swift 2 Version:

let trueDeepCopyArray = NSKeyedUnarchiver.unarchiveObjectWithData(
NSKeyedArchiver.archivedDataWithRootObject(oldArray))

Reply

#7
As the [Apple documentation about deep copies][apple] explicitly states:

> If you only need a *one-level-deep* copy:
>
> NSMutableArray *newArray = [[NSMutableArray alloc]
> initWithArray:oldArray copyItems:YES];


The above code creates a new array whose members are shallow copies of the members of the old array.

Note that if you need to deeply copy an entire nested data structure — what the linked Apple docs call a *true deep copy* — then this approach will not suffice. Please see the other answers here for that.

[apple]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through