首先來看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,深拷貝的是本身的對象,而對象里面的元素還是是指針拷貝,對于這種蘋果有種叫法是單層深復制。**