前言:
提到iOS中的淺復(fù)制和深復(fù)制的區(qū)別鸿捧,大家都知道淺復(fù)制過(guò)來(lái)的是對(duì)象的地址嗤军,而深復(fù)制靶瘸,相當(dāng)于重新開辟了內(nèi)存空間寝优,存儲(chǔ)這個(gè)對(duì)象条舔。
用代碼說(shuō)話
①單個(gè)對(duì)象的淺復(fù)制與深復(fù)制
/// 單個(gè)對(duì)象 淺復(fù)制、深賦值
- (void)ordinaryCopyVSMutableCopy {
NSString *str = @"hehe";
NSLog(@"源字符:%p",str);
//淺
NSString *cStr = [str copy];
NSLog(@"淺復(fù)制: Cstr = %p",cStr);
NSString *temp = [str copyWithZone:nil];
NSLog(@"copyWithZone: temp = %p",temp);
//深
NSString *mStr = [str mutableCopy];
NSLog(@"深復(fù)制: mStr = %p",mStr);
}
輸出結(jié)果:
單個(gè)對(duì)象深淺復(fù)制輸出結(jié)果.png
tips:可以看到
copy
乏矾、copyWithZone
方法都是淺復(fù)制逞刷,對(duì)象的地址并沒(méi)有改變,而mutableCopy
重新開辟了內(nèi)存控件妻熊,是深復(fù)制
數(shù)組及集合類對(duì)象的淺復(fù)制夸浅、深復(fù)制、完全復(fù)制
我們先定義一個(gè)原始數(shù)組
NSArray *originArr = [NSArray arrayWithObjects:@"1",@"2", nil];
NSLog(@"原數(shù)組 地址:%p",originArr);
NSLog(@"原數(shù)組中對(duì)象的地址: %p,%p \n",originArr[0],originArr[1]);
看代碼:
①對(duì)數(shù)組進(jìn)行淺復(fù)制
//對(duì)數(shù)組進(jìn)行淺復(fù)制
NSArray *copyArr = [originArr copy];
NSLog(@"淺復(fù)制 地址:%p",copyArr);
NSLog(@"淺復(fù)制數(shù)組中對(duì)象的地址: %p,%p \n",copyArr[0],copyArr[1]);
對(duì)比輸出結(jié)果看:
數(shù)組淺復(fù)制結(jié)果對(duì)比.png
tips:可以看到 不論是數(shù)組本身還是數(shù)組中的元素扔役,地址都沒(méi)有發(fā)生變化帆喇,這就是完完全全的淺復(fù)制
那么問(wèn)題1:
[NSArray arrayWithArray:originArr]
是淺復(fù)制 還是 深復(fù)制呢
NSArray *arr = [NSArray arrayWithArray:originArr];
NSLog(@"arrayWithArray深復(fù)制 地址:%p",arr);
NSLog(@"arrayWithArray深復(fù)制數(shù)組中對(duì)象的地址: %p,%p \n",arr[0],arr[1]);
結(jié)果:
arrayWithArray結(jié)果.png
tips:
arr
相比于源數(shù)組,算是一次深復(fù)制亿胸,但是數(shù)組中的元素地址依舊沒(méi)有發(fā)生變化
②對(duì)數(shù)組進(jìn)行深復(fù)制
NSArray *mCopyArr = [originArr mutableCopy];
NSLog(@"深復(fù)制 地址:%p",mCopyArr);
NSLog(@"深復(fù)制數(shù)組中對(duì)象的地址: %p,%p \n",mCopyArr[0],mCopyArr[1]);
打印地址發(fā)現(xiàn):
數(shù)組深復(fù)制.png
可以發(fā)現(xiàn)
mCopyArr
相比于原先的數(shù)組算是深復(fù)制了坯钦,但是內(nèi)部的元素依舊是原先數(shù)組中的元素
問(wèn)題2:[[NSArray alloc] initWithArray:.... copyItems:true]
是淺復(fù)制 還是 深復(fù)制呢
NSArray *array = [[NSArray alloc] initWithObjects:[[NSMutableString alloc] initWithString:@"1"], @"2",nil];
NSLog(@"array 地址: %p",array);
NSLog(@"array中元素的地址 :%p,%p",array[0],array[1]);
NSArray *arrWithCopyItem = [[NSArray alloc] initWithArray:array copyItems:true];
NSLog(@"arrWithCopyItem深復(fù)制 地址:%p",arrWithCopyItem);
NSLog(@"arrWithCopyItem深復(fù)制數(shù)組中對(duì)象的地址: %p,%p \n",arrWithCopyItem[0],arrWithCopyItem[1]);
輸出結(jié)果:
copyItems深復(fù)制、淺復(fù)制測(cè)試.png
可以看到侈玄,
arrWithCopyItem
對(duì)于源數(shù)組array
中的可變對(duì)象進(jìn)行的是深復(fù)制婉刀,對(duì)不可變對(duì)象做的是淺復(fù)制,所以可以稱,[[NSArray alloc] initWithArray:.... copyItems:true]
方法是與源數(shù)組做了一次不完全的深復(fù)制序仙,對(duì)于其中的不可變對(duì)象依舊是淺復(fù)制tips:字典的
[NSDictionary alloc] initWithDictionary:... copyItems:..
這個(gè)方法結(jié)果同上
問(wèn)題來(lái)了:這不算真正意義上的深復(fù)制突颊,即完全復(fù)制,那用什么方法可以實(shí)現(xiàn)完全復(fù)制呢?
②對(duì)數(shù)組進(jìn)行完全復(fù)制
方法有很多種,這里簡(jiǎn)單介紹兩種:
一:歸檔律秃、解擋操作
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:originArr];
NSData *aData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSArray *mmCopyArr = (NSArray *)aData;
NSLog(@"①歸檔深復(fù)制 地址:%p",mmCopyArr);
NSLog(@"①歸檔深復(fù)制數(shù)組中對(duì)象的地址: %p,%p \n",mmCopyArr[0],mmCopyArr[1]);
源數(shù)組.png
歸檔爬橡、解檔后.png
可以看到,不僅數(shù)組本身為深復(fù)制棒动,數(shù)組中的元素也都重新開辟了內(nèi)存空間
二:對(duì)數(shù)組進(jìn)行遍歷深復(fù)制糙申,該方法較為簡(jiǎn)單,就不寫代碼了