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.

  • forcopyWhere, the copied object isImmutable objectisShallow copy.The variable objectisDeep copy
  • formutableCopyBoth of themDeep copy
  • forcopyThe copied object is immutable, regardless of whether the copied object is mutable or not
  • formutableCopy 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

  1. 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

  1. 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.

  1. 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
  1. 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

  1. 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

  1. Custom object
  • forcopyCustom classes need to be addedNSCopyingProtocol and implement the correspondingcopyWithZone:Methods.
  • formutableCopyCustom classes need to be addedNSMutableCopyingProtocol 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,copyandstrongThere is no difference in keyword modification
  • For mutable strings:
    1. copyThe modified property is assigned oncecopyOperation (forMutable stringIs a copy of theDeep copy), which opens up a new memory address for it.
    2. strongDecorated properties do not proceedDeep copyOperation 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.