我記得剛開始開發(fā)的時(shí)候,有一段時(shí)間我一直以為淺拷貝==copy, mutableCopy==深拷貝, 由于沒有仔細(xì)研究,鬧過一段時(shí)間笑話。
深拷貝淺拷貝的概念直接抄錄如下:
淺拷貝:指針拷貝,不產(chǎn)生新的對(duì)象,源對(duì)象的引用計(jì)數(shù)器+1;
深拷貝:對(duì)象拷貝,會(huì)產(chǎn)生新的對(duì)象,源對(duì)象的引用計(jì)數(shù)器不變;
Example 1
NSArray * array = [NSArray arrayWithObjects:@"abc", @"lucy", nil];
NSMutableArray * array1 = [array copy];
// 調(diào)用這個(gè)方法會(huì)crash
// [array1 addObject:@"Lili"];
NSMutableArray * array2 = [array mutableCopy];
[array2 addObject:@"Lili"];
NSLog(@"array: %@ -%p",[array class],array);
NSLog(@"array1: %@ -%p",[array1 class],array1);
NSLog(@"array2: %@ -%p",[array2 class],array2);
打印結(jié)果:

example-1.png
不可變類型array的copy操作是淺拷貝,生成一個(gè)不可變對(duì)象;mutableCopy是深拷貝,生成一個(gè)可變對(duì)象。
Example 2
NSMutableArray * array = [NSMutableArray arrayWithObjects:@"abc", @"lucy", nil];
NSMutableArray * array1 = [array copy];
// 調(diào)用這個(gè)方法會(huì)crash
// [array1 addObject:@"Lili"];
NSMutableArray * array2 = [array mutableCopy];
[array2 addObject:@"Lili"];
NSLog(@"array: %@ -%p",[array class],array);
NSLog(@"array1: %@ -%p",[array1 class],array1);
NSLog(@"array2: %@ -%p",[array2 class],array2);
/ ** 打印結(jié)果
array: __NSArrayM -0x600002be7750
array1: __NSArrayI -0x6000025afe80
array2: __NSArrayM -0x600002be7a20
*/
可變類型array的copy操作是深拷貝,生成一個(gè)不可變對(duì)象;mutableCopy是深拷貝,生成一個(gè)可變對(duì)象。
| 原對(duì)象類型 | 拷貝方法 | 深/淺拷貝 | 副本對(duì)象類型 |
|---|---|---|---|
| NSArray | copy | 淺拷貝 | NSArray |
| NSArray | mutableCopy | 深拷貝 | NSMutableArray |
| NSMutableArray | copy | 深拷貝 | NSArray |
| NSMutableArray | mutableCopy | 深拷貝 | NSMutableArray |
Example 3 單層深拷貝和完全深拷貝
NSMutableString * str1 = [NSMutableString stringWithString:@"Bian"] ;
NSMutableString * str2 = [NSMutableString stringWithString:@"Sun"] ;
NSMutableArray * mutableArr = [[NSMutableArray alloc] initWithObjects:str1,str2, nil];
NSMutableArray * copyMutableArr = [mutableArr mutableCopy];
NSLog(@"mutableArr:%p %p %p",mutableArr,mutableArr[0],mutableArr[1]);
NSLog(@"copyMutableArr:%p %p %p",copyMutableArr,copyMutableArr[0],copyMutableArr[1]);
// 修改str1的值
[str1 insertString:@"abc" atIndex:0];
NSLog(@"mutableArr:%p %p %p",mutableArr,mutableArr[0],mutableArr[1]);
NSLog(@"copyMutableArr:%p %p %p",copyMutableArr,copyMutableArr[0],copyMutableArr[1]);
NSLog(@"%@",copyMutableArr[0]);
/** 打印結(jié)果:
mutableArr:0x600003ddaa90 0x600003ddaa30 0x600003dda9d0
copyMutableArr:0x600003ddaac0 0x600003ddaa30 0x600003dda9d0
mutableArr:0x600003ddaa90 0x600003ddaa30 0x600003dda9d0
copyMutableArr:0x600003ddaac0 0x600003ddaa30 0x600003dda9d0
copyMutableArr的str1的值:abcBian
*/
mutableArr的深拷貝copyMutableArr開辟了新的內(nèi)存,但是里面值得內(nèi)存地址還和mutableArr共享一份地址,明顯就是指針拷貝,所以說這不是完全意義上的深拷貝,叫單層深拷貝!
那么如何實(shí)現(xiàn)完全深拷貝呢?
如下
//只需這樣創(chuàng)建深拷貝,就是完全深拷貝
NSMutableArray * copyMutableArr = [[NSMutableArray alloc] initWithArray:mutableArr copyItems:YES];
結(jié)論:
- 可變對(duì)象的copy和mutableCopy方法都是深拷貝;
- 不可變對(duì)象的copy方法是淺拷貝,mutableCopy方法是深拷貝;
- copy方法返回的對(duì)象都是不可變對(duì)象。