谈谈iOS 中的深浅拷贝

760 阅读2分钟

深浅拷贝

深拷贝:新开辟一块空间,然后返回他的地址,修改原来的对象,新的对象不受影响。
浅拷贝:把原来对象的地址返回。

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都是深拷贝。我们所说的深拷贝其实只有一层,如果数组中含有子数组,是不管用的,这个时候要想保证全拷贝,应该用归档。