在开发工程中,很多时候我们要创建对象的副本,要创建副本,对象所在的类必须遵守 NSCopying 和 NSMutableCopying 的协议:
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(NSZone *)zone;
@end
一般Foundation的类都遵守这两个协议,都可以直接复制。
复制分多种情况
一:非容器类的不可变对象的复制,copy不产生副本,只有MutableCopy才产生副本。
1.不可变对象的copy
copy是一种浅拷贝,只复制对象指针的值,不产生副本,只增加对象的引用计数。
NSString * ns1 = [[NSString alloc] initWithFormat:@"%@",@"1234"]; NSString * copyns1 = [ns1 copy]; NSLog(@"copy: %lu %lu",ns1.retainCount,copyns1.retainCount);
2.不可变对象的MutableCopy
mutableCopy产生可变对象,也就是一个副本,是一种深拷贝,但不改变原对象的引用计数。
NSString * ns1 = [[NSString alloc] initWithFormat:@"%@",@"1234"]; NSMutableString * mcns1 = [ns1 mutableCopy]; NSLog(@"%lu %lu %lu",ns1.retainCount,copyns1.retainCount,mcns1.retainCount);
二:非容器类的可变对象的复制,不管是copy还是MutableCopy都会产生新的副本。
1.可变对象的copy
copy产生一个新的不可变对象。(产生副本)
NSMutableString * ms1 = [[NSMutableString alloc] initWithFormat:@"%@",@"4567" ]; NSString* copyms1 = [ms1 copy]; NSLog(@"muablecopy: %lu %lu",ms1.retainCount,copyms1.retainCount);
2.可变对象的MutableCopy
MutableCopy产生一个新的可变对象。(产生副本)
NSMutableString * ms1 = [[NSMutableString alloc] initWithFormat:@"%@",@"4567" ]; NSMutableString * mcms1 = [ms1 mutableCopy]; NSLog(@"%lu %lu %lu",ms1.retainCount,copyms1.retainCount,mcms1.retainCount);
三 不可变容器类的copy和MutableCopy (容器类的复制默认是浅复制,即只复制容器类对象本身,不复制容器里的对象)
1.copy不产生新的副本,只增加数组本身的引用计数,数组内的对象的引用计数没有增加。
NSArray *arr1=[NSArray arrayWithObjects:@1,@2,@3,@4,nil]; NSArray *copyArray=[arr1 copy]; NSLog(@"%p %p",arr1,copyArray); NSLog(@"%lu %lu",(unsigned long)arr1.retainCount,(unsigned long)copyArray.retainCount);
2.MutableCopy产生一个副本,是一个可变数组,原数组本身的引用计数没有增加,但数组内的对象的引用计数增加。
NSArray *arr1=[NSArray arrayWithObjects:@1,@2,@3,@4,nil]; NSMutableArray *copyArray=[arr1 mutableCopy]; NSLog(@"%p %p",arr1,copyArray); NSLog(@"%lu %lu",(unsigned long)arr1.retainCount,(unsigned long)copyArray.retainCount)
四 可变容器类的copy和MutableCopy
1.copy产生一个副本,是不可变的数组,数组内的对象的引用计数增加。
2.MutableCopy也产生一个副本,是可变的数组,数组内的引用计数增加。
关于Copy和MutableCopy的总结:
对于不可变的对象,Copy不产生新对象,其作用就相当于retain,增加引用计数。MutableCopy产生新的可变对象,原对象的引用计数不变。
对于可变对象来说,Copy和MutableCopy都产生副本,也就是新对象,但Copy是不可变的副本,MutableCopy是可变的副本。
关于Copy和MutableCopy结果的总结:
Copy的结果是不可变的,而MutableCopy的结果是可变的。