preface
-
Metaphorically, shallow copy creates a shortcut to a file that essentially points to the original file. Deep copy is the actual copy and paste of a file to form a separate new file.
-
Using the point to memory address view, the shallow-copied object points to the memory address of the copied object, and the deep-copied object points to a new memory address.
Copy and mutableCopy methods
Note that copy and mutableCopy are not just shallow and deep copies.
- for
copy
Where, the copied object isImmutable object
isShallow copy
.The variable object
isDeep copy
- for
mutableCopy
Both of themDeep copy
- for
copy
The copied object is immutable, regardless of whether the copied object is mutable or not - for
mutableCopy
The copied object is mutable regardless of whether the copied object is mutable
IOS objects can be roughly divided into container objects and non-container objects, and if we break it down, Can be divided into variable container object (NSMutableArray), immutable container object (NSArray), variable non container object (NSMutableString, NSMutableDictionary), Immutable non-container objects (NSString,NSDictionary).
Let’s verify the effect of copy and mutableCopy
- Non-container immutable objects
NSString *str1 = @" non-container-immutable object "; NSString *str2 = [str1 copy]; NSString *str3 = [str1 mutableCopy]; NSLog(@"str1:%p class:%@",str1,[str1 class]); NSLog(@"str2:%p class:%@",str2,[str2 class]); NSLog(@"str3:%p class:%@",str3,[str3 class]); Str1 :0x105718738 class:__NSCFConstantString str2:0x105718738 Class :__NSCFConstantString str3:0x60400024eb80 class:__NSCFStringCopy the code
Conclusion: for non-container-immutable objects, copy is a shallow copy and mutableCopy is a deep copy
- Non-container mutable objects
NSMutableString *str1 = [NSMutableString stringWithFormat:@" Non-container mutable object "]; NSMutableString *str2 = [str1 copy]; NSMutableString *str3 = [str1 mutableCopy]; NSLog(@"str1:%p class:%@",str1,[str1 class]); NSLog(@"str2:%p class:%@",str2,[str2 class]); NSLog(@"str3:%p class:%@",str3,[str3 class]); Str1:0x600000251Be0 Class :__NSCFString str2:0x600000251010 Class :__NSCFString str3: 0x600000251C40 class:__NSCFStringCopy the code
Conclusion: copy and mutableCopy are deep copies for non-container mutable objects
This conclusion actually explains the problem with copy instead of the strong keyword for NSString objects – the data security problem. See details below.
- Container immutable objects
NSArray *array1 = [NSArray arrayWithObjects:@" Non-containerimmutable object ",[NSMutableString stringWithFormat:@" Non-containerimmutable object "], nil]; NSArray *array2 = [array1 copy]; NSArray *array3 = [array1 mutableCopy]; NSLog(@"array:%p copyArray:%p mutableCopyArray:%p",array1,array2,array3); NSLog(@"array1[0]:%p array1[1]:%p ",array1[0] , array1[1]); NSLog(@"array2[0]:%p array2[1]:%p ",array2[0] , array2[1]); NSLog(@"array3[0]:%p array3[1]:%p ",array3[0] , array3[1]); / / print the results array: 0 x6040002312a0 copyArray: 0 x6040002312a0 mutableCopyArray: 0 x6040002544f0 array1 [0] : 0 x105718738 array1[1]:0x60400024eb80 array2[0]:0x105718738 array2[1]:0x60400024eb80 array3[0]:0x105718738 array3[1]:0x60400024eb80Copy the code
Conclusion: 1. Copy is a shallow copy and mutableCopy is a deep copy for container immutable objects
2. For elements in a container, 'copy' and 'mutableCopy' are both shallow copiesCopy the code
- Container mutable object
NSMutableArray array1 = [NSMutableArray arrayWithObjects:@" Non-container-immutable objects ",[NSMutableString stringWithFormat:@" Non-container-mutable objects "], nil]; NSMutableArray *array2 = [array1 copy]; NSMutableArray *array3 = [array1 mutableCopy]; NSLog(@"array1:%p array2:%p array3:%p",array1,array2,array3); NSLog(@"array1[0]:%p array1[1]:%p ",array1[0], array1[1]); NSLog(@"array2[0]:%p array2[1]:%p ",array2[0], array2[1]); NSLog(@"array3[0]:%p array3[1]:%p ",array3[0], array3[1]); Array1 :0x604000254820 array2: 0x604000231A00 Array3:0x6040002545B0 Array1 [0]:0x105718738 Array1 [1]:0x6040002544f0 array2[0]:0x105718738 array2[1]:0x6040002544f0 array3[0]:0x105718738 array3[1]:0x6040002544f0Copy the code
1. Copy and mutableCopy are deep copies of container mutable objects
2. Copy and mutableCopy are shallow copies of elements in a container
- Copy and mutableCopy after the object
NSString *str1 = @" non-container-immutable object "; NSMutableString *str2 = [str1 mutableCopy]; [str2 appendString:@"111"]; NSLog(@"str2:%@",str2); / / print the str2: non container immutable objects, 111 / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / NSMutableString *str1 = [NSMutableString stringWithFormat:@" Non-container mutable object "]; NSMutableString *str2 = [str1 copy]; [str2 appendString:@"111"]; / / perform [str2 appendString: @ "111"] error Terminating app due to uncaught exception 'NSInvalidArgumentException, reason: 'Attempt to mutate immutable object with appendString:'Copy the code
1. Mutable objects are mutable after executing mutable objects, regardless of whether they are mutable or not
2. The copied object cannot be changed, regardless of whether the copied object is mutable
- Custom object
- for
copy
Custom classes need to be addedNSCopying
Protocol and implement the correspondingcopyWithZone:
Methods. - for
mutableCopy
Custom classes need to be addedNSMutableCopying
Protocol and implement the correspondingmutableCopyWithZone:
Methods.
@interface Singer() <NSCopying>
@property (nonatomic, strong) NSString *name;
@end
- (id)copyWithZone:(NSZone *)zone {
Singer *singer = [[Singer allocWithZone:zone] init];
singer.name = self.name;
return singer;
}
Copy the code
NSString copy differs from strong
- For immutable strings,
copy
andstrong
There is no difference in keyword modification - For mutable strings:
copy
The modified property is assigned oncecopy
Operation (forMutable string
Is a copy of theDeep copy
), which opens up a new memory address for it.strong
Decorated properties do not proceedDeep copy
Operation does not open up a new memory address.
NSString * STR = @" I'm an immutable string "; self.strongStr = str; self.copyedStr = str; NSLog(@"str:%p, strongStr:%p, copyedStr:%p",str,self.strongStr,self.copyedStr); // Prints result STR: 0x10CD90978, strongStr: 0x10CD90978, copyedStr: 0x10CD90978Copy the code
When a string is immutable, self.strongStr and self.copyedStr are indistinguishable, pointing to the memory address of STR.
NSMutableString * STR = [NSMutableString stringWithFormat:@" I am a mutable string "]; self.strongStr = str; self.copyedStr = str; [STR appendString:@" ha ha ha "]; NSLog(@"str:%p, strongStr:%p, copyedStr:%p",str,self.strongStr,self.copyedStr); NSLog(@"str:%@, strongStr:%@, copyedStr:%@",str,self.strongStr,self.copyedStr); / / print results STR: 0 x6000002507d0, strongStr: 0 x6000002507d0, copyedStr: 0 x600000251760 STR: variable string ha ha ha, I'm a strongStr: I'm a variable string ha ha ha, CopyedStr: I'm a mutable stringCopy the code
When the string is mutable, self.copyedStr points to the new memory address, and self.copyedStr points to the memory address of STR.
What exactly is the problem with using the strong keyword to modify an NSString attribute? When we have finished assigning the strongStr attribute, we change the value of self. strongStr because it points to the same memory address. StrongStr has modified behavior without our knowledge, which is not secure. Therefore, when the type is not clear, it is generally recommended to use the copy keyword to modify an NSString attribute.