浅复制——即指针复制,不创建新的对象;
深复制——即内容复制,创建一个新的对象。
(这么精辟的话当然出自高手之口)
引自:http://www.jianshu.com/p/ebbac2fec4c6
1 NSString和NSMutableString
(1) NSString发送copy消息时会进行浅复制:
NSString *name = @"name";
NSString *nameFromCopy = [name copy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2283:101871] 0x1000020b0
[2283:101871] 0x1000020b0
看上去对NSString的copy好像什么都没做,实际上是有的,ARC会在后台调用retain给这个字符串添加一个引用计数。
(2)NSString发送mutableCopy消息是深复制:
NSString *name = @"name";
NSString *nameFromCopy = [name mutableCopy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2743:131031] 0x1000020b0
[2743:131031] 0x100700200
(3) 向NSMutableString发送copy消息会进行深复制:
NSMutableString *name = [[NSMutableString alloc] initWithString:@"name"];
NSString *nameFromCopy = [name copy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2270:97375] 0x100100540
[2270:97375] 0x656d616e45
(4) NSMutableString的mutableCopy消息是深复制:
NSMutableString *name = [[NSMutableString alloc] initWithString:@"name"];
NSString *nameFromCopy = [name mutableCopy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2753:133279] 0x1005034d0
[2753:133279] 0x100503650
小结:
2 NSArray和NSMutableArray
(1) NSArray的copy是浅复制
NSArray *array = [[NSArray alloc] init];
NSArray *arrayFromCopy = [array copy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2798:141184] 0x100501360
[2798:141184] 0x100501360
(2)NSMutable的copy是深复制
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *arrayFromCopy = [array copy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2871:152574] 0x100700420
[2871:152574] 0x100501360
(3)NSArray的mutableCopy是深复制
NSArray *array = [[NSArray alloc] init];
NSArray *arrayFromCopy = [array mutableCopy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2881:155075] 0x100201360
[2881:155075] 0x100700a90
(4)NSMutableArray的mutableCopy是深复制
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *arrayFromCopy = [array mutableCopy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2891:156290] 0x1007001e0
[2891:156290] 0x100700380
也就是说,得出了跟NSString和NSMutableString之间一样的结论??
表面上来看,确实是这样。但是,数组作为一个容器,肯定还要考虑里面的数据情况。我们尝试在数组里放点实验数据,比如几个字符串:
NSArray的copy:
//创建3个可变字符串
NSMutableString *string1 = [NSMutableString stringWithFormat:@"a"];
NSMutableString *string2 = [NSMutableString stringWithFormat:@"b"];
NSMutableString *string3 = [NSMutableString stringWithFormat:@"c"];
//将3个字符串放入数组中
NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
NSArray *arrayFromCopy = [array copy];
NSLog(@"%p", array); //输出原数组及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //输出copy的数组及其元素的地址
NSLog(@"%p", arrayFromCopy[0]);
NSLog(@"%p", arrayFromCopy[1]);
NSLog(@"%p", arrayFromCopy[2]);
[3141:182137] 0x100701030
[3141:182137] 0x100700200
[3141:182137] 0x1007003e0
[3141:182137] 0x100700440
[3141:182137] 0x100701030
[3141:182137] 0x100700200
[3141:182137] 0x1007003e0
[3141:182137] 0x100700440
NSArray的mutableCopy
NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
NSArray *arrayFromCopy = [array mutableCopy];
NSLog(@"%p", array); //输出原数组及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //输出copy的数组及其元素的地址
NSLog(@"%p", arrayFromCopy[0]);
NSLog(@"%p", arrayFromCopy[1]);
NSLog(@"%p", arrayFromCopy[2]);
[3151:184027] 0x100103410
[3151:184027] 0x1001024d0
[3151:184027] 0x100102390
[3151:184027] 0x1001023d0
[3151:184027] 0x100102bf0
[3151:184027] 0x1001024d0
[3151:184027] 0x100102390
[3151:184027] 0x1001023d0
所以,其实NSArray的mutableCopy只是对数组对象进行了深复制,而数组内元素依然是浅复制。像下图这样:
事实上NSMutableArray的copy和mutableCopy也是这样,为了节省篇幅我就不放代码了,有兴趣的朋友可以自己试一下。
如果想实现数组内元素也进行深复制,有个比较简单的方法,就是用NSArray提供的一个初始化方法
-(instancetype)initWithArray:copyItems:
NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
NSArray *arrayFromCopy = [[NSArray alloc] initWithArray:array copyItems:YES];
NSLog(@"%p", array); //输出原数组及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //输出copy的数组及其元素的地址
NSLog(@"%p", arrayFromCopy[0]);
NSLog(@"%p", arrayFromCopy[1]);
NSLog(@"%p", arrayFromCopy[2]);
[3166:189328] 0x100106fc0
[3166:189328] 0x100100270
[3166:189328] 0x100105eb0
[3166:189328] 0x100105f10
[3166:189328] 0x100106d90
[3166:189328] 0x6115
[3166:189328] 0x6215
[3166:189328] 0x6315
现在引用情况像这样:
我猜你现在肯定很想知道,下面这种情况的话,用上面的深复制方法能否奏效:(模仿歪果仁的口吻,听起来就像是一个很牛逼的人在说话一样)
//创建3个可变字符串
NSMutableString *string1 = [NSMutableString stringWithFormat:@"a"];
NSMutableString *string2 = [NSMutableString stringWithFormat:@"b"];
NSMutableString *string3 = [NSMutableString stringWithFormat:@"c"];
//将string1放入数组array_0中
NSArray *array_0 = [[NSArray alloc] initWithObjects:string1, nil];
//将array_0,string2,string3放入数组array中
NSArray *array = [NSArray arrayWithObjects:array_0, string2, string3, nil];
//复制�数组
NSArray *arrayFromCopy = [[NSArray alloc] initWithArray:array copyItems:YES];
//输出
NSLog(@"%p", array); //输出原数组及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //输出copy的数组及其元素的地址
NSLog(@"%p", arrayFromCopy[0]);
NSLog(@"%p", arrayFromCopy[1]);
NSLog(@"%p", arrayFromCopy[2]);
printf("\n");
NSLog(@"%p", array[0][0]); //输出原数组和copy数组的数组的字符串string1地址
NSLog(@"%p", arrayFromCopy[0][0]);
[3203:205170] 0x100106ef0
[3203:205170] 0x1001069b0
[3203:205170] 0x100100200
[3203:205170] 0x100100260
[3203:205170] 0x100106f20
[3203:205170] 0x1001069b0
[3203:205170] 0x6215
[3203:205170] 0x6315
[3203:205170] 0x1001062f0
[3203:205170] 0x1001062f0
这就是答案:
可见NSArray的实例方法-(instancetype)initWithArray:copyItems:的深复制到三维数组已经力不从心了,如果想对三维或以上的数组进行彻底深复制,就必须使用杀手锏——归档。
关于归档,笔者另文:http://www.jianshu.com/p/a0b994d34c0a
这2篇文章循环引用了:)