深复制与浅复制 需要遵守NSCopying, NSMutableCopying 2个协议
什么是copy Copy的字面意思是“复制”、“拷贝”,是一个产生副本的过程 常见的复制有:文件复制 作用:利用一个源文件产生一个副本文件 特点: 修改源文件的内容,不会影响副本文件 修改副本文件的内容,不会影响源文件 OC中的copy 作用:利用一个源对象产生一个副本对象 特点: 修改源对象的属性和行为,不会影响副本对象 修改副本对象的属性和行为,不会影响源对象
如何使用copy功能 一个对象可以调用copy或mutableCopy方法来创建一个副本对象 copy : 创建的是不可变副本(如NSString、NSArray、NSDictionary) mutableCopy :创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary) 使用copy功能的前提 copy : 需要遵守NSCopying协议,实现copyWithZone:方法 @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end mutableCopy : 需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法 @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end
深复制(深拷贝,内容拷贝,deep copy) 源对象和副本对象是不同的两个对象 源对象引用计数器不变, 副本对象计数器为1(因为是新产生的) 本质是:产生了新的对象 浅复制(浅拷贝,指针拷贝,shallow copy) 源对象和副本对象是同一个对象 源对象(副本对象)引用计数器 + 1, 相当于做一次retain操作 本质是:没有产生新的对象
实例1 NSString和NSMutableString:
NSString *str1 = @"abc"; NSString *str2 = @"abc"; BOOL isEquals = str1==str2?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSString *str3 = [str1 copy]; isEquals = str3==str2?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSMutableString *str4 = [str1 mutableCopy]; isEquals = str4==str1?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSLog(@"-----------------------"); NSString *str5 = @"abc"; NSMutableString *str6 = [NSMutableString stringWithFormat:@"abc"]; isEquals = str5==str6?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSString *str7 = [str6 copy]; isEquals = str7==str2?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSMutableString *str8 = [str6 mutableCopy]; isEquals = str8==str6?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同");
运行结果:
2015-01-01 14:48:07.742 深复制与浅复制[934:56160] =相同= 2015-01-01 14:48:07.743 深复制与浅复制[934:56160] =相同= 2015-01-01 14:48:07.743 深复制与浅复制[934:56160] =不相同= 2015-01-01 14:48:07.743 深复制与浅复制[934:56160] ----------------------- 2015-01-01 14:48:07.744 深复制与浅复制[934:56160] =不相同= 2015-01-01 14:48:07.744 深复制与浅复制[934:56160] =不相同= 2015-01-01 14:48:07.744 深复制与浅复制[934:56160] =不相同= Program ended with exit code: 0
注意:NSString copy产生的不可变数据对象也是指向原对象,上面str1和str3
实例2 NSArray和NSMutableArray:
NSArray *array1 = @[@1,@2,@3]; NSArray *array2 = @[@1,@2,@3]; BOOL isEquals = array1 == array2 ? YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSArray *array3 = [array1 copy]; isEquals = array3 == array1 ? YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSMutableArray *array4 = [array1 mutableCopy]; isEquals = array4 == array1 ? YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); // NSLog(@"%@",array1); // NSLog(@"%@",array4); [array4 addObject:@4]; // NSLog(@"%@",array1); NSLog(@"%@",array4); NSLog(@"--------------------------"); NSMutableArray *array5 = [NSMutableArray arrayWithObjects:@1,@2,@3, nil]; NSArray *array6 = [array5 copy]; isEquals = array5 == array6 ? YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); NSMutableArray *array8 = [array5 mutableCopy]; isEquals = array5 == array8 ? YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); // NSLog(@"%@",array8); [array8 addObject:@4]; // NSLog(@"%@",array5); NSLog(@"%@",array8);
运行结果:
2015-01-01 15:00:30.950 深复制与浅复制[980:59234] =不相同= 2015-01-01 15:00:30.951 深复制与浅复制[980:59234] =相同= 2015-01-01 15:00:30.951 深复制与浅复制[980:59234] =不相同= 2015-01-01 15:00:30.952 深复制与浅复制[980:59234] ( 1, 2, 3, 4 ) 2015-01-01 15:00:30.952 深复制与浅复制[980:59234] -------------------------- 2015-01-01 15:00:30.952 深复制与浅复制[980:59234] =不相同= 2015-01-01 15:00:30.952 深复制与浅复制[980:59234] =不相同= 2015-01-01 15:00:30.952 深复制与浅复制[980:59234] ( 1, 2, 3, 4 ) Program ended with exit code: 0
注意:NSArray copy产生的不可变数据对象也是指向原对象,上面array1和array3
实例4 NSDictionary和NSMutableDictionary 跟上面情况一样:
实例5:测试不管产生可变还是不可变对象,数组中存储内容对象都还是指向同一份对象
@interface Person : NSObject //<NSCopying, NSMutableCopying> @property (nonatomic,copy) NSString *name; @property (nonatomic,assign) int age; - (void)eat; - (instancetype)initWithName:(NSString *)name age:(int)age; + (instancetype)personWithName:(NSString *)name age:(int)age; @end
#import "Person.h" @implementation Person - (void)eat{ NSLog(@"%s",__func__); } + (instancetype)personWithName:(NSString *)name age:(int)age{ return [[self alloc] initWithName:name age:age]; } - (instancetype)initWithName:(NSString *)name age:(int)age{ if (self == [super init]) { self.name = name; self.age = age; } return self; } - (NSString *)description{ return [NSString stringWithFormat:@"name=%@ age=%d",_name,_age]; } //- (id)copyWithZone:(NSZone *)zone{ // Person *person = [[Person allocWithZone:zone] init]; // person.name = [self.name copy]; // person.age = self.age; // return person; //} // //- (id)mutableCopyWithZone:(NSZone *)zone{ // Person *person = [[Person allocWithZone:zone] init]; // person.name = [self.name mutableCopy]; // person.age = self.age; // return person; //} @end
Person *p1 = [Person personWithName:@"zhangsan" age:20]; Person *p2 = [Person personWithName:@"lisi" age:21]; Person *p3 = [Person personWithName:@"wangwu" age:22]; NSMutableArray *array1 = [NSMutableArray arrayWithObjects:p1,p2,p3, nil]; NSLog(@"%@",array1); p1.name = @"zhangsan111"; NSLog(@"%@",array1); NSArray *array2 = [array1 copy]; NSLog(@"%@",array2); BOOL isEquals = array1 == array2?YES:NO; NSLog(@"=%@=",isEquals?@"相同":@"不相同"); isEquals = array1[0] == array2[0]; NSLog(@"=%@=",isEquals?@"相同":@"不相同");
运行结果:
2015-01-01 15:18:58.814 深复制与浅复制[1100:64607] ( "name=zhangsan age=20", "name=lisi age=21", "name=wangwu age=22" ) 2015-01-01 15:18:58.815 深复制与浅复制[1100:64607] ( "name=zhangsan111 age=20", "name=lisi age=21", "name=wangwu age=22" ) 2015-01-01 15:18:58.815 深复制与浅复制[1100:64607] ( "name=zhangsan111 age=20", "name=lisi age=21", "name=wangwu age=22" ) 2015-01-01 15:18:58.816 深复制与浅复制[1100:64607] =不相同= 2015-01-01 15:18:58.816 深复制与浅复制[1100:64607] =相同=
说明复制后2个数组中存储的内容对象是相同的。