1.先來看一段代碼
NSArray *array;
NSMutableArray *arrM = [NSMutableArray arrayWithObjects:@"a",@"b",@"c", nil];
array = arrM;
NSLog(@"-----%@",array);
[arrM addObject:@"d"];
NSLog(@"=======%@",array);
//輸出結果:
-----(
a,
b,
c
)
=======(
a,
b,
c,
d
)
思考:arrM先賦值給array,再增加d元素,為什么array中卻也加入了新的元素?
這里先分析造成這個情況的原因如下圖:
- 所以當arrM新增元素時,array中的值也隨之發(fā)生了改變.那么如何解決這種情況呢?讓array中的值不隨arrM的改變而改變?
解決方式
//造成這種問題的關鍵代碼
//array = arr;
array = [arr copy];
copy方法做了那些事情?起到了什么樣的作用,下面我們仔細研究一下.
2.copy铆农、mutableCopy
- 首先我們要知道,什么是copy.就像我們將桌面上的一文件進行
ctrl+c
、ctrl+v
一樣,會根據(jù)之前的文件,生成一個副本文件,副本文件中的內容與源文件中相同.copy與mutableCopy也是一樣的道理,一般
情況下,調用對象的copy发钝、mutableCopy會生成一個新的對象,一定要注意這里說的是一般情況下,后面會說明不一般
的情況
copy顿涣、mutableCopy的本質:修改原來的對象不能影響到拷貝出來得對象;修改拷貝出來的對象也不能影響到原來的對象,總之就是兩個對象互不影響.
- 下面以數(shù)組為例,總結一下copy、mutableCopy的具體作用
- 例一:由一個可變數(shù)組,生成另外一個可變數(shù)組
NSMutableArray *arrM1 = [NSMutableArray array];
NSMutableArray *arrM2 = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
arrM1 = [arrM2 mutableCopy];
[arrM1 addObject:@"aa"];
[arrM2 addObject:@"bb"];
NSLog(@"arrM1 = %@,arrM2 = %@,arrM1內存地址 = %p,arrM2內存地址 = %p",arrM1,arrM2,arrM1,arrM2);
//輸出結果:
arrM1 = (
1,
2,
aa
),arrM2 = (
1,
2,
bb
),arrM1內存地址 = 0x600000242130,arrM2內存地址 = 0x6000002418c0
-
在內存中的表現(xiàn)形式
總結:該方式會生成一個新的對象,兩個對象之間互不影響
例二:由一個不可變數(shù)組,生成一個可變數(shù)組
NSMutableArray *arrM = [NSMutableArray array];
NSArray *dataArray = @[@"1",@"2"];
arrM = [dataArray mutableCopy];
[arrM addObject:@"3"];
NSLog(@"arrM = %@,dataArray = %@,arrM內存地址 = %p,dataArray內存地址 = %p",arrM,dataArray,arrM,dataArray);
//輸出:
arrM = (
1,
2,
3
),dataArray = (
1,
2
),arrM內存地址 = 0x600000055cc0,dataArray內存地址 = 0x600000222b20
總結:該方式會生成一個新的對象,兩個對象之間互不影響,內存中的表現(xiàn)形式與例一相同.
例三:由一個可變數(shù)組,生成一個不可變數(shù)組
NSArray *dataArray;
NSMutableArray *arrM = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
dataArray = [arrM copy];
[arrM addObject:@"3"];
NSLog(@"dataArray = %@,arrM = %@,dataArray內存地址 = %p,arrM內存地址 = %p",dataArray,arrM,dataArray,arrM);
//輸出:
dataArray = (
1,
2
),arrM = (
1,
2,
3
),dataArray內存地址 = 0x604000220ea0,arrM內存地址 = 0x604000244320
總結:該方式會生成一個新的對象,兩個對象之間互不影響,內存中的表現(xiàn)形式與例一相同.
例四:根據(jù)一個不可變數(shù)組,生成一個不可變數(shù)組.
注意:這種情況就是上面說的不一般的情況
NSArray *arr1;
NSArray *arr2 = @[@"1",@"2",@"3"];
arr1 = [arr2 copy];
NSLog(@"arr1 = %@,arr2 = %@,arr1內存地址 = %p,arr2內存地址 = %p",arr1,arr2,arr1,arr2);
//輸出:
arr1 = (
1,
2,
3
),arr2 = (
1,
2,
3
),arr1內存地址 = 0x60000045df10,arr2內存地址 = 0x60000045df10
- 總結:該方式
不
會生成一個新的對象,兩個對象之間互不影響
前三個例子都會生成一個新的對象,保證兩個對象之間進行修改,互不影響,但是例四在不生成新對象的情況下,依然能保證兩個對象之間進行修改,互不影響.
原因: 因為原來的對象是不能修改的, 拷貝出來的對象也是不能修改的,既然兩個都不能修改, 所以永遠不能影響到另外一個對象, 那么就滿足了我們上面提到的copy酝豪、mutableCopy的本質,
3.淺拷貝、深拷貝
在調用了copy精堕、mutableCopy方法之后:
- 如果沒有生成新的對象, 我們稱之為淺拷貝, 本質就是指針拷貝,比如例四.
- 如果生成了新的對象, 我們稱之為深拷貝, 本質就是會創(chuàng)建一個新的對象.比如例一孵淘、例二、例三.
4.補充
- 在明白了淺拷貝歹篓、深拷貝之后,我們回到最初的那段代碼
NSArray *array;
NSMutableArray *arrM = [NSMutableArray arrayWithObjects:@"a",@"b",@"c", nil];
array = arrM;
NSLog(@"-----%@",array);
[arrM addObject:@"d"];
NSLog(@"=======%@",array);
//輸出結果:
-----(
a,
b,
c
)
=======(
a,
b,
c,
d
)
這里出現(xiàn)這種情況的原因,上面也說過了就是
array = arrM;
就是這句代碼造成的.而且其效果與淺拷貝相同,就是拷貝了一個指針指向了數(shù)組對象.
所以:=
是淺拷貝,大多數(shù)情況下應該是淺拷貝吧.深拷貝的情況沒有注意過,如果寫的不對,請指證,我及時修改.3Q
5.類比Foundation框架中的其他數(shù)據(jù)類型
-
話不多說直接上圖,沒圖說個吉米巴特勒