在Objective-C中對(duì)象之間的拷貝分為淺拷貝和深拷貝拿撩。說白了崭别,對(duì)非容器類的淺拷貝就是拷貝對(duì)象的地址捎迫,對(duì)象里面存的內(nèi)容仍然是一份,沒有新的內(nèi)存被分配澳叉。對(duì)非容器類的深拷貝就是重寫分配一塊內(nèi)存,然后把另一個(gè)對(duì)象的內(nèi)容原封不動(dòng)的給我拿過來沐悦。對(duì)容器類的深拷貝是對(duì)容器中的每個(gè)元素都進(jìn)行拷貝成洗,容器類的淺拷貝是對(duì)容器里的內(nèi)容不進(jìn)行拷貝,兩個(gè)容器的地址是不同的藏否,但容器里的所裝的東西是一樣的瓶殃,在一個(gè)容器中修改值,則另一個(gè)淺拷貝的容器中的值也會(huì)變化副签。所以對(duì)非容器類看對(duì)象是否為深拷貝還是淺拷貝就得看對(duì)象的內(nèi)存地址就可以看出來遥椿,而對(duì)容器類基矮,我們則進(jìn)一步看容器中的內(nèi)容了。因?yàn)镺C中用引用計(jì)數(shù)的方式來進(jìn)行內(nèi)存管理的所以我們也可以通過觀察對(duì)象retainCount的變化來分析對(duì)象之間是否是深拷貝還是淺拷貝冠场。
那么對(duì)象大體都分為哪些類型呢家浇?從可變不可變和容器類非容器類的角度可以把對(duì)象分為一下幾種,那么什么是容器類呢?容器類就是用該類聲明的對(duì)象可以去容納其他對(duì)象碴裙,非容器類則沒有這些功能钢悲。那么什么是可變或者不可變的呢?可變的時(shí)內(nèi)存的大小是可以根據(jù)需要改變舔株,而不可變的就是分配完以后就不可以改變他的內(nèi)存空間
- 非容器不可變對(duì)象莺琳,比如NSString
2.非容器可變對(duì)象:比如NSMutableString
3.容器類不可變對(duì)象: 比如NSArray
4.容器類可變對(duì)象: 比如NSMutableArray
在觀察深淺拷貝之前先得了解一下retain,copy和mutableCopy的特點(diǎn)载慈,特點(diǎn)如下:
1.retain:始終是淺復(fù)制惭等。引用計(jì)數(shù)每次加一。返回對(duì)象是否可變與被復(fù)制的對(duì)象保持一致办铡。
2.copy:對(duì)于可變對(duì)象為深復(fù)制辞做,引用計(jì)數(shù)不改變;對(duì)于不可變對(duì)象是淺復(fù)制, 引用計(jì)數(shù)每次加一料扰。始終返回一個(gè)不可變對(duì)象凭豪。
3.mutableCopy:始終是深復(fù)制,引用計(jì)數(shù)不改變晒杈。始終返回一個(gè)可變對(duì)象嫂伞。
深拷貝和淺拷貝
從圖我們看出來淺拷貝只是拷貝了指針,而并未拷貝對(duì)象本身拯钻。而深拷貝則是指針和對(duì)象本身都進(jìn)行了拷貝
代碼演示
使用不可變集合對(duì)象
NSArray *array = @[@"4444"];
NSArray *array2 = array;
NSLog(@"array === %p %p", &array, array);
NSLog(@"array2 === %p %p", &array2, array2);
打印結(jié)果
array === 0x7fff5fbff738 0x100403120
array2 === 0x7fff5fbff730 0x100403120
array與array2指針地址不同
mutableCopy
NSArray *array = @[@"4444"];
NSArray *array2 = [array mutableCopy];
NSLog(@"array === %p %p", &array, array);
NSLog(@"array2 === %p %p", &array2, array2);
打印結(jié)果
array === 0x7fff5fbff738 0x100203520
array2 === 0x7fff5fbff730 0x1002024e0
我們發(fā)現(xiàn)兩者的指針指著不一樣帖努,內(nèi)容也不一樣,也就是說粪般,實(shí)現(xiàn)了內(nèi)容和指針的拷貝拼余。也就是深拷貝
用copy時(shí)候的打印結(jié)果是什么?
打印結(jié)果
array === 0x7fff5fbff738 0x100202b90
array2 === 0x7fff5fbff730 0x100202b90
結(jié)果是內(nèi)容沒有拷貝亩歹,而指針進(jìn)行了拷貝匙监。故copy為淺拷貝
使用可變對(duì)象
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"111", @"222", nil];
NSMutableArray *array1 = [mutableArray copy];
NSLog(@"mutable ===== %p %p", &mutableArray, mutableArray);
NSLog(@"array1 ===== %p %p", &array1, array1);
mutable ===== 0x7fff5fbff758 0x100203cb0
array1 ===== 0x7fff5fbff750 0x100203170
指針進(jìn)行了拷貝,內(nèi)容也進(jìn)行了拷貝小作。所以是深拷貝亭姥。
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"1111",@"22222", nil];
NSMutableArray *array = [mutableArray mutableCopy];
NSLog(@"mutable ===== %p %p", &mutableArray, mutableArray);
NSLog(@"array1 ===== %p %p", &array, array);
打印結(jié)果
mutable ===== 0x7fff5fbff758 0x100401270
array1 ===== 0x7fff5fbff750 0x100403230
其指針和內(nèi)容都已經(jīng)進(jìn)行了改變。所以這個(gè)時(shí)候mutableCopy便是深拷貝了顾稀。
對(duì)于使用可變對(duì)象時(shí)达罗,copy和mutableCopy都是深拷貝。
那深拷貝和淺拷貝在使用上的區(qū)別呢静秆?
NSArray *mutableArray = @[@"111"];
NSMutableArray *array = [mutableArray copy];[array addObject:@"333"];
NSLog(@"%@", array);
打印結(jié)果
-[__NSSingleObjectArrayI addObject:]
說明array是不可變數(shù)組
那如何改變array呢粮揉?
NSArray *mutableArray = @[@"111"];
NSMutableArray *array = [mutableArray mutableCopy];
[array addObject:@"333"];
NSLog(@"%@", array);
我們發(fā)現(xiàn)此時(shí)array是可以更改的對(duì)象
最終結(jié)論
對(duì)于不可變對(duì)象而言巡李,copy便是淺拷貝,而mutableCopy是深拷貝扶认。
對(duì)于可變對(duì)象而言侨拦,copy和mutableCopy都是深拷貝。但是copy出來的對(duì)象是不可變的蝠引,而mutableCopy則是可變對(duì)象阳谍。