先说结论
- 可变对象的copy和mutableCopy都是深拷贝,mutableCopy是单层深拷贝
- 不可变对象的copy是浅拷贝,mutableCopy是深拷贝
- copy出来的是不可变对象,mutableCopy出来的是可变对象
- 如果需要容器类完全深拷贝,容器内元素需要实现NSCopying和NSMutableCopying协议,并且使用带有copyItems的方法
测试
不可变对象
- (void)testInmutable{
NSLog(@"================================");
NSLog(@" 不可变对象测试");
NSLog(@"================================\n");
Person *obj = [[Person alloc]init];
NSArray *array = [NSArray arrayWithObject:obj];
NSMutableArray *mutableArray = [array mutableCopy];
NSArray *copyArray = [array copy];
NSLog(@"-------------容器类-------------");
NSLog(@"array: %p-%@ class:%@",array,array,NSStringFromClass([array class]));
NSLog(@"copyArray: %p-%@ class:%@",copyArray,copyArray,NSStringFromClass([copyArray class]));
NSLog(@"mutableArray: %p-%@ class:%@\n",mutableArray,mutableArray,NSStringFromClass([mutableArray class]));
NSString *str = @"123";
NSString *copyStr = [str copy];
NSString *mutableStr = [str mutableCopy];
NSLog(@"-------------非容器类-------------");
NSLog(@"str: %p---%@ class:%@",str,str,NSStringFromClass([str class]));
NSLog(@"copyStr: %p---%@ class:%@",copyStr,copyStr,NSStringFromClass([copyStr class]));
NSLog(@"mutableStr: %p---%@ class:%@\n",mutableStr,mutableStr,NSStringFromClass([mutableStr class]));
}
可变对象
- (void)testMutable{
NSLog(@"================================");
NSLog(@" 可变对象测试");
NSLog(@"================================\n");
Person *obj= [[Person alloc]init];
obj.mName = @"name";
NSMutableArray *array = [NSMutableArray arrayWithObject:obj];
NSArray *copyArray = [array copy];
NSMutableArray *mutableArray = [array mutableCopy];
NSMutableArray *mutableArray1 = [NSMutableArray arrayWithArray:array];
NSMutableArray *mutableArray2 = [[NSMutableArray alloc]initWithArray:array copyItems:YES];
obj.mName = @"newName";
NSLog(@"-------------容器类-------------");
NSLog(@"array: %p-%@ class:%@ name:%@",array,array,NSStringFromClass([array class]),((Person *)[array firstObject]).mName);
NSLog(@"copyArray: %p-%@ class:%@ name:%@",copyArray,copyArray,NSStringFromClass([copyArray class]),((Person *)[copyArray firstObject]).mName);
NSLog(@"mutableArray: %p-%@ class:%@ name:%@",mutableArray,mutableArray,NSStringFromClass([mutableArray class]),((Person *)[mutableArray firstObject]).mName);
NSLog(@"mutableArray1: %p-%@ class:%@ name:%@",mutableArray1,mutableArray1,NSStringFromClass([mutableArray1 class]),((Person *)[mutableArray1 firstObject]).mName);
NSLog(@"mutableArray2: %p-%@ class:%@ name:%@\n",mutableArray2,mutableArray2,NSStringFromClass([mutableArray2 class]),((Person *)[mutableArray2 firstObject]).mName);
NSMutableString *str = [NSMutableString stringWithString:@"123"];
NSString *copyStr = [str copy];
NSString *mutableStr = [str mutableCopy];
NSLog(@"-------------非容器类-------------");
NSLog(@"str: %p---%@ class:%@",str,str,NSStringFromClass([str class]));
NSLog(@"copyStr: %p---%@ class:%@",copyStr,copyStr,NSStringFromClass([copyStr class]));
NSLog(@"mutableStr: %p---%@ class:%@\n",mutableStr,mutableStr,NSStringFromClass([mutableStr class]));
}
打印结果
开发时需要注意的
- NSString,NSArray,NSDictionary类型的属性需要用copy修饰
- 因为如果从mutable对象赋值后,copy会深拷贝mutable对象,并且变成不可变类型,这样在mutable对象再有增删操作时不会对copy修饰的属性造成影响,如果是strong修饰的属性就会跟着改变了。但是容器类因为是单层深拷贝,所以如果对元素的某个属性进行修改,copy后的对象也会被修改