NSString NSArray的copy和mutableCopy

淺復(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é):

Numbers制表

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é)論??

Numbers制表

表面上來看,確實是這樣。但是,數(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ù)制。像下圖這樣:

Numbers繪圖

事實上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)在引用情況像這樣:


Numbers繪圖

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

Numbers繪圖
//創(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

這就是答案:


Numbers繪圖

可見NSArray的實例方法-(instancetype)initWithArray:copyItems:的深復(fù)制到三維數(shù)組已經(jīng)力不從心了,如果想對三維或以上的數(shù)組進行徹底深復(fù)制,就必須使用殺手锏——歸檔。
關(guān)于歸檔,筆者另文:http://www.itdecent.cn/p/a0b994d34c0a

這2篇文章循環(huán)引用了:)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文為轉(zhuǎn)載: 作者:zyydeveloper 鏈接:http://www.itdecent.cn/p/5f776a...
    Buddha_like閱讀 1,017評論 0 2
  • 為什么很多內(nèi)置類如UITableView的delegate屬性都是assign而不是retain? 所有的引用計數(shù)...
    煙雨平生花飛舞閱讀 1,279評論 0 3
  • 前言 不敢說覆蓋OC中所有copy的知識點,但最起碼是目前最全的最新的一篇關(guān)于 copy的技術(shù)文檔了。后續(xù)發(fā)現(xiàn)有新...
    zyydeveloper閱讀 3,708評論 4 35
  • 1、對象拷貝有兩種方式:淺復(fù)制和深復(fù)制。顧名思義,淺復(fù)制,并不拷貝對象本身,僅僅是拷貝指向?qū)ο蟮闹羔槪簧顝?fù)制是直接...
    滴答大閱讀 849評論 0 2
  • D7阿爾法號阿基米德艙110-黃丹 今天的導(dǎo)讀船長提到了魚、漁、道三者之間的意義和關(guān)系,讓我想起了這句名言:師者,...
    Michelle沐晨閱讀 290評論 0 0

友情鏈接更多精彩內(nèi)容