概念
對(duì)象拷貝有兩種方式:淺復(fù)制和深復(fù)制。顧名思義构诚,淺復(fù)制,并不拷貝對(duì)象本身铆惑,僅僅是拷貝指向?qū)ο蟮闹羔樂吨觯簧顝?fù)制是直接拷貝整個(gè)對(duì)象內(nèi)存到另一塊內(nèi)存中。
再簡(jiǎn)單些說(shuō):淺復(fù)制就是指針拷貝员魏;深復(fù)制就是內(nèi)容拷貝丑蛤。
1. 非集合類對(duì)象的copy和mutableCopy
系統(tǒng)非集合類對(duì)象指的是 NSString,NSMutableString撕阎,NSNumber...之類的對(duì)象受裹。
① 不可變對(duì)象,以NSString為例:
NSString *originStr = @"origin";
NSString *originStrCopy = [originStr copy];//copy
NSMutableString *originStrMutableCopy = [originStr mutableCopy];//mutableCopy
內(nèi)存截圖為:從上面的內(nèi)存截圖可以看出闻书,不可變對(duì)象copy內(nèi)存地址沒(méi)有變化名斟,而mutableCopy內(nèi)存地址發(fā)生了變化脑慧。
② 可變對(duì)象魄眉,以NSMutableString為例:
NSMutableString *mutableOriginStr = [NSMutableString stringWithString:@"mutableOrigin"];
NSMutableString *mutableOriginStrCopy = [mutableOriginStr copy];//copy
NSMutableString *mutableOriginStrMutableCopy = [mutableOriginStr mutableCopy];//mutableCopy
內(nèi)存截圖為:從上面的內(nèi)存截圖可以看出,可變對(duì)象copy和mutableCopy內(nèi)存地址都發(fā)生了變化闷袒。
非集合類總結(jié):
對(duì)不可變對(duì)象復(fù)制:copy是指針復(fù)制(淺拷貝)坑律,mutableCopy是內(nèi)容復(fù)制(深拷貝)。
對(duì)可變對(duì)象復(fù)制:copy和mutableCopy都是內(nèi)容復(fù)制(深拷貝)囊骤,但是copy返回的是不可變對(duì)象晃择。
2. 集合類對(duì)象的copy和mutableCopy
① 不可變對(duì)象,以NSArray為例:
NSArray *originArray = @[[NSMutableString stringWithString:@"a"],@"b",@"c"];
NSArray *originArrayCopy = [originArray copy];//copy
NSMutableArray *originArrayMutableCopy = [originArray mutableCopy];//mutableCopy
內(nèi)存截圖為:從上圖可以看出也物,不可變對(duì)象的copy內(nèi)存地址沒(méi)變宫屠,mutableCopy內(nèi)存地址發(fā)生了變化,但是不論copy還是mutableCopy滑蚯,集合內(nèi)的對(duì)象的內(nèi)存地址并沒(méi)有發(fā)生變化浪蹂,說(shuō)明copy和mutableCopy對(duì)于集合內(nèi)的對(duì)象來(lái)說(shuō)抵栈,都是只復(fù)制了指針。
添加一個(gè)元素:
[originArrayMutableCopy addObject:@"d"];
內(nèi)存截圖為:刪除一個(gè)元素
[originArrayMutableCopy removeLastObject];
內(nèi)存截圖為:修改一個(gè)元素:
NSMutableString *testString = [originArrayMutableCopy firstObject];
//testString = @"a changeValue";這樣寫是有問(wèn)題的坤次,會(huì)改變testString的指針古劲,其實(shí)是將@"a changeValue"臨時(shí)對(duì)象賦給了testString
[testString appendString:@" changeValue"];
內(nèi)存截圖為:可以看到,當(dāng)一個(gè)集合里的對(duì)象改變了缰猴,其他集合里的對(duì)象也改變了产艾,說(shuō)明指針指向的是同一塊內(nèi)存地址。
② 可變對(duì)象滑绒,以NSMutableArray為例:
NSMutableArray *mutableOriginArray = [[NSMutableArray alloc] initWithArray:@[@"a",@"b",@"c"] copyItems:YES];
NSArray *mutableOriginArrayCopy = [mutableOriginArray copy];
NSMutableArray *mutableOriginArrayMutableCopy = [mutableOriginArray mutableCopy];
內(nèi)存截圖為:從上圖可以看出闷堡,可變對(duì)象的copy和mutableCopy內(nèi)存地址都發(fā)生了變化,但是不論copy還是mutableCopy疑故,集合內(nèi)的對(duì)象的內(nèi)存地址并沒(méi)有發(fā)生變化缚窿,說(shuō)明copy和mutableCopy對(duì)于集合內(nèi)的對(duì)象來(lái)說(shuō),都是只復(fù)制了指針焰扳。
集合類總結(jié)
對(duì)不可變對(duì)象復(fù)制:copy是指針復(fù)制(淺拷貝)倦零,mutableCopy是內(nèi)容復(fù)制(深拷貝)。
對(duì)可變對(duì)象復(fù)制:copy和mutableCopy都是內(nèi)容復(fù)制(深拷貝)吨悍,但是copy返回的是不可變對(duì)象扫茅。
與非集合類不同的是:集合內(nèi)的對(duì)象都是指針復(fù)制!S稀葫隙!,即所謂的集合的單層深復(fù)制(one-level-deep copy)躏仇。
集合類真正意義的深拷貝
想要實(shí)現(xiàn)真正意義上的深復(fù)制(即集合對(duì)象和集合內(nèi)的對(duì)象都進(jìn)行內(nèi)容復(fù)制)恋脚,可以用下面的方法:
NSMutableArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:mutableOriginArray]];
內(nèi)存截圖為:
從上面兩張內(nèi)存截圖可以看出,使用歸檔的方法實(shí)現(xiàn)了真正的元素對(duì)象的拷貝焰手。
參考文檔:
(1) Blog:copy 與 mutableCopy
(2) iPhone Dev:iOS開(kāi)發(fā)之深拷貝與淺拷貝(mutableCopy與Copy)詳解
(3) 《招聘一個(gè)靠譜的iOS》面試題參考答案
(4) iOS 集合的深復(fù)制與淺復(fù)制