lead
When it comes to object replication, we can't get around the distinction between shallow replication and deep replication. What do they mean?
- Shallow copy: only the pointer of the object is copied. Two objects still point to the content of the same address. Operating one will affect the value of the other.
- Deep copy: copy the contents of objects. Two objects point to the contents of two different addresses. Operating one will not affect the value of the other.
In OC, because the memory is managed by memory counting, the count of the same content will be increased by one during shallow replication, but not for deep replication.
In OC, there are two methods for copying: copy and mutableCopy. Which is shallow copy and which is deep copy?
Non collection object
First, the objects are roughly divided into two categories: non collection objects and collection objects. As for why, we will talk about collection objects later.
Non collection objects refer to objects whose contents are concrete, such as NSString and NSNumber. For objects like NSString, there is also a related object called NSMutableString. Therefore, non collection objects can be divided into variable objects and immutable objects.
The meaning of copy and mutableCopy is:
- For immutable non collection objects (such as NSString), the copy operation is a shallow copy, only pointers will be copied, and the mutableCopy operation is a deep copy,
- For variable non collection objects (such as NSMutableString), both copy and mutableCopy are deep copies, and a new same content will be created to return. However, note that copy returns immutable objects, that is, even if you copy one NSMutableString, return it to another NSMutableString, and then change the NSMutableString, Will report an error.
The code is as follows:
NSString *string = @"origin"; NSString *stringCopy = [string copy];// Shallow replication NSMutableString *stringMCopy = [string mutableCopy];// Deep replication NSMutableString *string = [NSMutableString stringWithString: @"origin"]; NSString *stringCopy = [string copy];// Deep replication NSMutableString *mStringCopy = [string copy];// Deep replication NSMutableString *stringMCopy = [string mutableCopy];// Deep replication [mStringCopy appendString:@"mm"]; // crash
Collection object
The non collection object is mentioned above. What is a collection object? Collection objects refer to NSArray, NSDictionary and NSSet, which contain other objects.
Why make this distinction? Because the two concepts of shallow replication and deep replication are not complete, they should be more accurately divided into three types: shallow replication, deep replication and complete deep replication.
In OC, when you make a deep copy of a collection object, the deep copy is only a single layer, and the element objects in the collection are actually just references. Not every layer is a deep copy. In this case, apple defines it as one-level-deep copy. Only by deep copying each layer in the set can it be called complete deep copy.
Let's talk about simple shallow replication and deep replication. In fact, they are similar to non collection objects:
- For immutable collection objects (such as NSArray), the copy operation is a shallow copy, only pointers will be copied, and the mutableCopy operation is a deep copy,
- For variable collection objects (such as NSMutableArray), both copy and mutableCopy are deep copies, and a new same content will be created to return. However, two points should be paid attention to: first, copy returns an immutable object; second, as mentioned above, this deep copy is only a single-layer deep copy, and the elements contained in it are still shallow copies of pointers.
The code is:
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]; NSArray *copyArray = [array copy];// Shallow replication NSMutableArray *mCopyArray = [array mutableCopy];// Single layer deep replication NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil]; NSArray *copyArray = [array copy];// Single layer deep copy, return immutable object NSMutableArray *mCopyArray = [array mutableCopy];// Single layer deep replication
What if you want to do a full deep copy?
There are two methods:
- One method is as follows:
NSDictionary shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:YES];
If copyItems is set to YES, deep copy will be attempted for each object in the collection, but the element objects in the collection are required to follow the NSCopying protocol, otherwise an error will be reported. But this is actually a single-layer deep copy of the element layer, and there will be no complete deep copy in the future.
- Another method is to archive and de archive the collection (see Portal: archiving of iOS storage mode):
NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];
junction
The above are various applications of shallow replication and deep replication in OC. To test whether the operation is shallow replication or deep replication, you can see whether the reference count of the object increases:
NSLog(@"mArray retain count: %d", [mArray retainCount]);// Not available under ARC
Or directly check whether the addresses of the two objects are consistent:
NSLog(@"string Address of its own pointer:%x", &str); NSLog(@"string Address of the object pointed to by the pointer:%p", str);