淺復(fù)制——即指針復(fù)制,不創(chuàng)建新的對象;
深復(fù)制——即內(nèi)容復(fù)制,創(chuàng)建一個新的對象。
(這么精辟的話當(dāng)然出自高手之口)
引自:http://www.itdecent.cn/p/ebbac2fec4c6
1 NSString和NSMutableString
(1) NSString發(fā)送copy消息時會進行淺復(fù)制:
NSString *name = @"name";
NSString *nameFromCopy = [name copy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2283:101871] 0x1000020b0
[2283:101871] 0x1000020b0
看上去對NSString的copy好像什么都沒做,實際上是有的,ARC會在后臺調(diào)用retain給這個字符串添加一個引用計數(shù)。
(2)NSString發(fā)送mutableCopy消息是深復(fù)制:
NSString *name = @"name";
NSString *nameFromCopy = [name mutableCopy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2743:131031] 0x1000020b0
[2743:131031] 0x100700200
(3) 向NSMutableString發(fā)送copy消息會進行深復(fù)制:
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消息是深復(fù)制:
NSMutableString *name = [[NSMutableString alloc] initWithString:@"name"];
NSString *nameFromCopy = [name mutableCopy];
NSLog(@"%p", name);
NSLog(@"%p", nameFromCopy);
[2753:133279] 0x1005034d0
[2753:133279] 0x100503650
小結(jié):

2 NSArray和NSMutableArray
(1) NSArray的copy是淺復(fù)制
NSArray *array = [[NSArray alloc] init];
NSArray *arrayFromCopy = [array copy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2798:141184] 0x100501360
[2798:141184] 0x100501360
(2)NSMutable的copy是深復(fù)制
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *arrayFromCopy = [array copy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2871:152574] 0x100700420
[2871:152574] 0x100501360
(3)NSArray的mutableCopy是深復(fù)制
NSArray *array = [[NSArray alloc] init];
NSArray *arrayFromCopy = [array mutableCopy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2881:155075] 0x100201360
[2881:155075] 0x100700a90
(4)NSMutableArray的mutableCopy是深復(fù)制
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *arrayFromCopy = [array mutableCopy];
NSLog(@"%p", array);
NSLog(@"%p", arrayFromCopy);
[2891:156290] 0x1007001e0
[2891:156290] 0x100700380
也就是說,得出了跟NSString和NSMutableString之間一樣的結(jié)論??

表面上來看,確實是這樣。但是,數(shù)組作為一個容器,肯定還要考慮里面的數(shù)據(jù)情況。我們嘗試在數(shù)組里放點實驗數(shù)據(jù),比如幾個字符串:
NSArray的copy:
//創(chuàng)建3個可變字符串
NSMutableString *string1 = [NSMutableString stringWithFormat:@"a"];
NSMutableString *string2 = [NSMutableString stringWithFormat:@"b"];
NSMutableString *string3 = [NSMutableString stringWithFormat:@"c"];
//將3個字符串放入數(shù)組中
NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
NSArray *arrayFromCopy = [array copy];
NSLog(@"%p", array); //輸出原數(shù)組及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //輸出copy的數(shù)組及其元素的地址
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); //輸出原數(shù)組及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //輸出copy的數(shù)組及其元素的地址
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只是對數(shù)組對象進行了深復(fù)制,而數(shù)組內(nèi)元素依然是淺復(fù)制。像下圖這樣:

事實上NSMutableArray的copy和mutableCopy也是這樣,為了節(jié)省篇幅我就不放代碼了,有興趣的朋友可以自己試一下。
如果想實現(xiàn)數(shù)組內(nèi)元素也進行深復(fù)制,有個比較簡單的方法,就是用NSArray提供的一個初始化方法
-(instancetype)initWithArray:copyItems:
NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
NSArray *arrayFromCopy = [[NSArray alloc] initWithArray:array copyItems:YES];
NSLog(@"%p", array); //輸出原數(shù)組及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //輸出copy的數(shù)組及其元素的地址
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
現(xiàn)在引用情況像這樣:

我猜你現(xiàn)在肯定很想知道,下面這種情況的話,用上面的深復(fù)制方法能否奏效:(模仿歪果仁的口吻,聽起來就像是一個很牛逼的人在說話一樣)

//創(chuàng)建3個可變字符串
NSMutableString *string1 = [NSMutableString stringWithFormat:@"a"];
NSMutableString *string2 = [NSMutableString stringWithFormat:@"b"];
NSMutableString *string3 = [NSMutableString stringWithFormat:@"c"];
//將string1放入數(shù)組array_0中
NSArray *array_0 = [[NSArray alloc] initWithObjects:string1, nil];
//將array_0,string2,string3放入數(shù)組array中
NSArray *array = [NSArray arrayWithObjects:array_0, string2, string3, nil];
//復(fù)制?數(shù)組
NSArray *arrayFromCopy = [[NSArray alloc] initWithArray:array copyItems:YES];
//輸出
NSLog(@"%p", array); //輸出原數(shù)組及其元素的地址
NSLog(@"%p", array[0]);
NSLog(@"%p", array[1]);
NSLog(@"%p", array[2]);
printf("\n");
NSLog(@"%p", arrayFromCopy); //輸出copy的數(shù)組及其元素的地址
NSLog(@"%p", arrayFromCopy[0]);
NSLog(@"%p", arrayFromCopy[1]);
NSLog(@"%p", arrayFromCopy[2]);
printf("\n");
NSLog(@"%p", array[0][0]); //輸出原數(shù)組和copy數(shù)組的數(shù)組的字符串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:的深復(fù)制到三維數(shù)組已經(jīng)力不從心了,如果想對三維或以上的數(shù)組進行徹底深復(fù)制,就必須使用殺手锏——歸檔。
關(guān)于歸檔,筆者另文:http://www.itdecent.cn/p/a0b994d34c0a
這2篇文章循環(huán)引用了:)