首先来看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,深拷贝的是本身的对象,而对象里面的元素还是是指针拷贝,对于这种苹果有种叫法是单层深复制。**