preface

I always thought I understood deep and light copies very well. I was recently asked this question in an interview,

What would happen if a mutable string called copy? Off the top of my head, I pointed out that it was a pointer copy, which is a shallow copy, and went back and debugged it and found it was wrong.

Shallow copy

It’s a little bit easier to understand, so let’s just look at the picture.

Shallow copy: to copy a pointer to the same memory area. Real memory is not copied

Deep copy

Deep copy: Copy data to a new memory area. Pointers point to the copied data area

Deep and light copy in iOS, strong, copy, mutableCopy

Strong: a shallow copy of a pointer reference. So let’s test that out

  1. Create two new classes A and B and declare the property testString with strong
@interface A : NSObject

@property (nonatomic,strong)NSMutableString *testString;

@end

@interface B : NSObject

@property (nonatomic,strong)NSMutableString *testString;

@end
Copy the code
  1. Create an NSMutableString and assign to the A and B objects
    A *a = [[A alloc]init];
    NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
    NSLog(@"Address of raw string :%p",string);
    a.testString = string;
    NSLog(@"A string address :%p",a.testString);
    B *b = [[B alloc]init];
    b.testString = a.testString ;
    NSLog(@"B object string address :%p",b.testString);
Copy the code

The result is as follows, and the actual object is the same.

2018-06-29 17:17:36.669945+0800 testArray[31561:804923] Original String address :0x600000249480 2018-06-29 17:17:36.670097+0800 TestArray [31561:804923] A String address :0x600000249480 2018-06-29 17:17:36.670192+0800 testArray[31561:804923] B Address of the string :0x600000249480

This means that A does something like appendString on A mutable string using an attribute, and the value in B is modified.

I won’t test it here, but if you’re interested, you can test it yourself.

Copy: Here we look at the system’s NSstring, NSArray object copy after what

An interesting phenomenon is that we create a new NSMutableString, copy, and then use that copy object to call the MutableString special appendString to modify the string

    NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
    NSLog(@"Address of raw string :%p",string);
    
    NSMutableString *copyString = [string copy];
    NSLog(@"Copy string address :%p",copyString);
    
    [copyString appendString:@"test"];
Copy the code

The result?

Flash back! Why is that? If you look closely, our MutableString called copy, the memory location of the copied string has changed, which means that a deep copy has taken place.

Then we call the appendString method with copyString and there’s a very regular flash back, and the log shows that we copied NSTaggedPointerString, which is an immutable string.

That is to say, the mutable string after copy will be deep copy, copy out is an immutable string!

Now let’s test what happens if we copy an NSString

    NSString *string = [NSString stringWithFormat:@"name"];
    NSLog(@"Address of raw string :%p",string);
    
    NSString *copyString = [string copy];
    NSLog(@"Copy string address :%p",copyString);
Copy the code

2018-06-29 17:30:51.985051+0800 testArray[31672:813638] Original String address: 0xA000000656D616E4 2018-06-29 17:30:51.985173+0800 TestArray [31672:813638] copy string address: 0xA000000656D616e4

It turns out that this is a shallow copy and the address hasn’t changed.

NSArray is also the same verification results, here will not be posted, interested children can try their own

This leads us to the conclusion that copy is not necessarily a shallow copy, but an immutable string or array. If the object being copied is a mutable array or string, then a deep copy will occur, and vice versa.

For strings and arrays, MutableCopy must be a deep copy, and the copied object must be a mutable string or array. Even if the copied object is an immutable string.

conclusion

1. The character string copied must be immutable. If the character string is mutable, the deep copy is immutable; otherwise, it is shallow copy. 2. Mutablecopy must be a deep copy of an immutable string or array, even if it’s an immutable string or array.

thinking

  1. It’s easy to see why NSString uses the copy modifier. With the copy modifier, even if the property is copied from a mutable string, it will be deeply copied to an immutable string. In other words, the property string will not be affected by the modification of the source string, increasing the robustness of the code.

  2. A shallow copy of immutable strings and arrays is also understandable. Since the data source itself is immutable, that is, secure, it is obviously reasonable for the system to default to a shallow copy of the data.