深浅拷贝
深拷贝:新开辟一块空间,然后返回他的地址,修改原来的对象,新的对象不受影响。
浅拷贝:把原来对象的地址返回。
NSString& mutableString
NSMutableString* mutabelstring = [NSMutableString stringWithString:@"abc"];
self.pname = mutabelstring;
[mutabelstring appendString:@"wwwwwwwwww]"];
NSLog(@"mutableString:%@,self.pname:%@",mutabelstring,self.pname);
当@property (nonatomic, strong) NSMutableString *pname 时, 打印结果

当@property (nonatomic, copy) NSMutableString *pname 时, 打印结果

NSMutableArray
NSMutableArray* stringArray1 = [NSMutableArray arrayWithArray:@[@"a",@"b",@"c",@"d"]];
NSLog(@"%p-%p-%p",stringArray1,[stringArray1 copy],[stringArray1 mutableCopy]);
NSLog(@"%@-%@-%@",stringArray1.class,[[stringArray1 copy] class],[[stringArray1 mutableCopy] class]);
第一行打印数组的地址,第二行打印数组的类型,结果如下:
0x2831335a0 - 0x2831334e0 - 0x283133720
__NSArrayM- __NSFrozenArrayM- __NSArrayM
可以看出对于可变数组来说,copy和mutablecopy都会新开辟一块地址,去存原来的值,所以都是深拷贝。当然,copy完会是一个不可变数组,mutablecopy完还是一个可变数组。所以代码中这么写肯定会有问题的。
@property (nonatomic, copy) NSMutableArray *array;
NSArray
NSArray* stringArray1 = @[@"a",@"b",@"c",@"d"];
NSLog(@"%p-%p-%p",stringArray1,[stringArray1 copy],[stringArray1 mutableCopy]);
NSLog(@"%@-%@-%@",stringArray1.class,[[stringArray1 copy] class],[[stringArray1 mutableCopy] class]);
看下打印结果:
0x282874990- 0x282874990- 0x282874a50
__NSArrayI- __NSArrayI- __NSArrayM
对于不可变数组,copy是一个浅拷贝,还是原来的地址,新的数组是一个不可变数组,mutablecopy是一个深拷贝,地址变化了,新的数组是可变数组。
多层深拷贝
有时候我们碰到这样到需求:
NSMutableString* string = [NSMutableString stringWithString:@"a"];
NSArray* array = @[string,@"b",@"c",@"d"];
[string appendString:@"dddd"];
NSLog(@"%@",[array mutableCopy]);
这时候array的第一个元素跟着变化。打印结果 ( adddd, b, c, d ) ,这是因为我们所谓的深拷贝,只是一个单层拷贝,它只是新生成了一个数组,数组里存的依然还是原来对象的指针值,如何避免这种情况呢,可以用这个函数: NSMutableArray * stringArray1 = [[NSMutableArray alloc]initWithArray:array copyItems:YES]; 打印结果: a, b, c, d。 但是这个函数只能深拷贝一层,如果是这样: NSMutableString* string = [NSMutableString stringWithString:@"a"];
NSArray* array = @[@[string,@"b",@"c",@"d"],@"bb",@"cd",@"dd"];
NSMutableArray * stringArray1 = [[NSMutableArray alloc]initWithArray:array copyItems:YES];
[string appendString:@"dddd"];
NSLog(@"%@-%@",stringArray1,[array mutableCopy]);
打印结果如下( ( adddd, b, c, d ), bb, cd, dd )----( ( adddd, b, c, d ),bb, cd, dd )
这个时候要用到归档 NSMutableString* string = [NSMutableString stringWithString:@"a"]; NSArray* array = @[@[string,@"b",@"c",@"d"],@"bb",@"cd",@"dd"];
NSMutableArray * stringArray1 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
[string appendString:@"dddd"];
NSLog(@"%@-%@",stringArray1,[array mutableCopy]);
打印如下: ( ( a, b, c, d ), bb, cd, dd )-( ( adddd, b, c, d ), bb, cd, dd )
总结:
当修饰可变类型的属性时,如NSMutableArray、NSMutableDictionary、NSMutableString,用strong。
当修饰不可变类型的属性时,如NSArray、NSDictionary、NSString,用copy。
针对不可变数组,copy是浅拷贝,mutablecopy是深拷贝。 针对可变数组,copy和mutablecopy都是深拷贝。我们所说的深拷贝其实只有一层,如果数组中含有子数组,是不管用的,这个时候要想保证全拷贝,应该用归档。