copy和mutableCopy 浅拷贝和深拷贝

首先来看copy和MutableCopy的实现过程。
一个对象要实现copy,首先要继承NSCopying的协议,然后实现 + (id)copyWithZone:(struct _NSZone * )zone
同理,一个对象要实现mutableCopy,首先要继承NSMutableCopying的协议,然后实现+ (id)mutableCopyWithZone:(struct _NSZone * )zone

  • copy只会产生不可变副本对象
  • mutableCopy只会产生可变副本对象

再来看看容器类对象的概念:主要有NSArray、NSSet和NSDictionary,以及他们的Mutable子类。非容器对象的主要有NSString、NSNumber等。


然后分情况讨论一下copy 和 mutableCopy是深拷贝还是浅拷贝。

  • 对非容器对象,对不可变对象拷贝,copy为浅拷贝,mutableCopy是深拷贝
NSString * original = @"original";
NSString * string1 = [original copy];
NSMutableString * string2 = [original mutableCopy];
NSLog(@"%@ %p",original,original);
NSLog(@"%@ %p",string1,string1);
NSLog(@"%@ %p",string2,string2);

这里可以看出来original 和string1 的地址一样 ,original 和string2地址不一样。

  • 对非容器对象,对可变对象拷贝,copy和mutableCopy都是深拷贝,但是copy返回的对象不可变
NSMutableString * original = [NSMutableString stringWithString:@"original"];
NSString * string1 = [original copy];
NSMutableString * string2 = [original mutableCopy];
NSMutableString * string3 = [original copy];
NSLog(@"%@ %p",original,original);
NSLog(@"%@ %p",string1,string1);
NSLog(@"%@ %p",string2,string2);
NSLog(@"%@ %p",string3,string3);
    //error copy的是不可变对象 不能执行appendString方法
//    [string3 appendString:@"add"];

original 和string1、 string2、string3的地址都不一样,但是string3 返回的是不可变类型,不能执行appendString方法

  • 对容器对象,对不可变对象拷贝,copy为浅拷贝,mutableCopy是深拷贝
    NSArray * original = @[@"a",@"b",@"c"];
    NSArray * array1 = [original copy];
    NSMutableArray * array2 = [original mutableCopy];
    NSLog(@"%@ %p",original,original);
    NSLog(@"%@ %p",array1,array1);
    NSLog(@"%@ %p",array2,array2);

以上结论对容器对象仍然适用。 original和array1的地址是一样的,original和array2不一样。

  • 对容器对象,对可变对象拷贝,copy和mutableCopy都是深拷贝,但是copy返回的对象不可变
    NSMutableArray * original = [NSMutableArray arrayWithArray:   @[@"a",@"b",@"c"]];
    
    NSArray * array1 = [original copy];
    NSMutableArray * array2 = [original mutableCopy];
    NSMutableArray * array3 = [original copy];
    
    NSLog(@"%@ %p",original,original);
    NSLog(@"%@ %p",array1,array1);
    NSLog(@"%@ %p",array2,array2);
    NSLog(@"%@ %p",array3,array3);
    
    //    [array3 addObject:@"d"];

以上结论对容器对象仍然适用。 original和array1、array2、array3不一样。array3返回的是不可变类型 addObject不可执行。

  • 对容器对象,copy和MutableCopy的深拷贝,是拷贝对象本身array,array集合内部的元素还是指针拷贝。
    NSArray * origin = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
    NSArray * array1 = [origin copy];
    NSMutableArray * array2 = [origin mutableCopy];
    
    NSMutableString * string = [origin objectAtIndex:0];
    [string appendString:@"add"];
    
    NSLog(@"%@",origin);
    NSLog(@"%@",array1);
    NSLog(@"%@",array2);

origin、array1、array2都变成了 @[@"aadd",@"b",@"c"]

** 综上,对于不可变对象的copy是浅拷贝,mutableCopy是深拷贝。对于可变对象,copy和mutableCopy都是深拷贝。对于容器类的copy和mutableCopy,深拷贝的是本身的对象,而对象里面的元素还是是指针拷贝,对于这种苹果有种叫法是单层深复制。**

你可能感兴趣的:(copy和mutableCopy 浅拷贝和深拷贝)