其實也不算深度解析啦,主要是題目要響亮一點大家才有看的欲望嘛!?。?/p>
首先關于Copy想必在面試題中大家見過很多,下面我就寫一下我對Copy的理解。
1.Copy是什么???
copy和mutableCopy是方法,是NSObject內定義的方法。
2.Copy有什么用???
copy顧名思義就是拷貝或者說克隆,所以copy的目的就是復制一份原來的內容,進一步思考為什么需要拷貝?顯然:拷貝的目的就是改變原來的內容不影響副本,改變副本也不影響原來的內容。
3.從NSString,NSMutableString,NSArray,NSMutableArray說明深拷貝和淺拷貝的區別
首先大家來想一下為什么要用到Copy??Copy的目的所在是什么?為什么需要生成一個新的對象呢???
Copy是為了互不干擾,生成兩個對象是為了相互改變的時候不影響另外一個對象。
其次大家要牢記一點,使用Copy方法得到的是不可變對象,使用mutableCopy方法得到的必須是可變對象。
一.NSString、NSMutableString非容器對象分析
1.不可變字符串的copy和mutableCopy
NSString *str = @"xiaoming";
NSString *str1 = [str copy];
NSMutableString * str2 = [str mutableCopy];
NSLog(@"----str:%p,%@,%@----str1:%p,%@,%@----str2:%p,%@,%@",str,str,NSStringFromClass([str class]),str1,str1,NSStringFromClass([str1 class]),str2,str2,NSStringFromClass([str2 class]));
打印結果如下:
----str:0x10c8e4068,xiaoming,__NSCFConstantString----str1:0x10c8e4068,xiaoming,__NSCFConstantString----str2:0x608000266ac0,xiaoming,__NSCFString
通過上面的打印結果大家可以看到不可變的字符串經過copy之后沒有生成對象,得到的是不可變字符串,經過mutableCopy之后生成了新的對象,得到是可變字符串。
為什么copy沒有得到對象呢???因為原來的對象是不可以修改的,新拷貝的對象也是不可修改的,所以不會影響到另外一個對象。已經符合拷貝的目的 了,所以,OC為了對內存進行優化, 就不會生成一個新的對象。
為什么mutableCopy會生成新的對象呢?生成的是一個可變對象,這樣兩個對象其中一個對象改變而不影響另外一個對象。
2.可變字符串的copy和mutableCopy
NSMutableString *mulStr = [NSMutableString stringWithFormat:@"abc"];
NSString *mulStr1 = [mulStr copy];
NSMutableString * mulStr2 = [mulStr mutableCopy];
NSLog(@"----str:%p,%@,%@----str1:%p,%@,%@----str2:%p,%@,%@",mulStr,mulStr,NSStringFromClass([mulStr class]),mulStr1,mulStr1,NSStringFromClass([mulStr1 class]),mulStr2,mulStr2,NSStringFromClass([mulStr2 class]));
打印結果如下:
----str:0x600000260180,abc,__NSCFString----str1:0xa000000006362613,abc,NSTaggedPointerString----str2:0x6000002601c0,abc,__NSCFString
通過上面的打印結果可以看出來可變字符串經過copy和mutableCopy之后都創建了新的對象。經過copy之后得到的是不可變字符串,經過mutableCopy之后 得到的是可變字符串。
為什么都會生成對象呢???因為可變字符串本來就是可以改變的,為了改變互不干擾,從而生成新的對象,符合拷貝的目的。
二:NSArray、NSMutableArray容器對象分析
首先容器對象和非容器對象一樣同樣遵從下面的總結:
如果對一不可變對象復制,copy是指針復制(淺拷貝)、mutableCopy就是對象復制(深拷貝)。
如果是對可變對象復制,都是深拷貝,但是copy返回的對象是不可變的。
1.NSArray的copy和mutableCopy?
NSArray *array = [[NSArray alloc]initWithObjects:[NSMutableString stringWithFormat:@"a"],@"b",@"c", nil];
NSArray *array1 = [array copy];
NSMutableArray *array2 = [array mutableCopy];
// NSArray *array3 = [array mutableCopy];
NSArray *array3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
NSLog(@"----array:%p,----array1:%p,-----array2:%p,----array3:%p",array,array1,array2,array3);
NSMutableString *str1 = [array objectAtIndex:0];
[str1 appendString:@"hahhaha"];
[array2 insertObject:@"111111" atIndex:0];
NSMutableString *str2 = [array2 objectAtIndex:1];
[str2 appendString:@"111111"];
NSLog(@"----array:%@,----array1:%@,-----array2:%@,----array3:%@",array,array1,array2,array3);
打印結果如下:
?----array:0x608000242070,----array1:0x608000242070,-----array2:0x608000242b50,----array3:0x608000242d90
?----array:(
ahahhaha111111,
b,
c
),----array1:(
ahahhaha111111,
b,
c
),-----array2:(
111111,
ahahhaha111111,
b,
c
),----array3:(
a,
b,
c
)
通過上面的打印可以看出來NSArray 經過Copy之后沒有創建對象,經過mutableCopy之后創建了新的對象,具體原因和NSString一樣,但是里面的元素對象還是指針拷貝,要想做到對象拷貝,可以使用歸檔的方法。
2.NSMutableArray 的copy和MutableCopy
NSMutableArray *mulArray = [[NSMutableArray alloc]initWithObjects:[NSMutableString stringWithFormat:@"abc"],@"def", nil];
NSMutableArray *mulArray1 = [mulArray copy];
NSMutableArray *mulArray2 = [mulArray mutableCopy];
NSLog(@"----array:%p,----arrar1:%p,----array2:%p",mulArray,mulArray1,mulArray2);
NSMutableString *mulstr = [mulArray objectAtIndex:0];
[mulstr appendString:@"abc"];
NSLog(@"----array:%@,-----array1:%@,-----array2:%@",mulArray,mulArray1,mulArray2);
NSLog(@"----array:%@,-----array1:%@,-----array2:%@",NSStringFromClass([mulArray class]) ,NSStringFromClass([mulArray1 class]),NSStringFromClass([mulArray2 class]));
打印結果如下:
----array:0x60000005af40,----arrar1:0x60000002b1a0,----array2:0x60000005ad60
----array:(
abcabc,
def
),-----array1:(
abcabc,
def
),-----array2:(
abcabc,
def
)
通過上面的打印可以看出來NSArray 經過Copy和mutableCopy之后都創建新的對象,具體原因和NSString一樣,但是里面的元素對象還是指針拷貝,要想做到對象拷貝,可以使用歸檔的方法。
但是大家還要牢記一點:NSMutableArray多次copy每次都會新建對象而NSArray多次copy只新建一次對象。
4.總結
正是因為調用copy方法有時候會生成一個新的對象, 有時候不會生成一個新的對象所以:
如果沒有生成新的對象, 我們稱之為淺拷貝, 本質就是指針拷貝
如果生成了新的對象, 我們稱之為深拷貝, 本質就是會創建一個新的對象
最后:最重要的還是記住拷貝的目的,這樣理解深淺拷貝都會變得非常簡單,改變原來的內容不影響副本,改變副本也不影響原來的內容