對(duì)于iOS中淺拷貝和淺拷貝,大家只是模糊的知道前者是復(fù)制了一份對(duì)象的地址,也就是同一個(gè)對(duì)象增加了一個(gè)指向它的指針,而后者是一個(gè)新的指針變量指向一個(gè)新的對(duì)象,這個(gè)新的對(duì)象是原對(duì)象的復(fù)制品,即對(duì)象屬性完全相同只是位于不同的內(nèi)存空間。但針對(duì)數(shù)組類(lèi)型的對(duì)象時(shí)還需要更仔細(xì)理解一下。
數(shù)組類(lèi)型的淺拷貝同樣是開(kāi)辟一個(gè)新的指針指向該數(shù)組,兩個(gè)指針操作的是同一個(gè)數(shù)組;而深拷貝分為兩種情況,一是拷貝數(shù)組中的對(duì)象地址至一個(gè)新的數(shù)組,新數(shù)組中對(duì)象和原數(shù)組中對(duì)象是相同的內(nèi)存地址即相同的實(shí)例,二是拷貝數(shù)組中的對(duì)象至一個(gè)新的數(shù)組,新數(shù)組中對(duì)象和原數(shù)組中對(duì)象是不同的實(shí)例。
還是直接用代碼輸出拷貝的數(shù)組地址來(lái)解釋吧。
首先創(chuàng)建數(shù)組arrayA,其中添加了兩個(gè)對(duì)象person1和person2,并且輸出arrayA的地址如圖1所示。
NSMutableArray *arrayA = [[NSMutableArray alloc]initWithCapacity:0];
Person *person1 = [[Person alloc]initWithHeight:180 withAge:18 withName:@"Joe"];
Person *person2 = [[Person alloc]initWithHeight:150 withAge:15 withName:@"Kate"];
[arrayA addObject:person1];
[arrayA addObject:person2];
NSLog(@"arrayA:%p,%@",arrayA,arrayA);

然后創(chuàng)建arrayB數(shù)組,用來(lái)拷貝arrayA,并且向arrayB中添加對(duì)象person3,輸出arrayB和arrayA的地址如圖2所示,兩個(gè)數(shù)組完全一致,arrayB其實(shí)就是arrayA的淺拷貝。
NSMutableArray *arrayB = arrayA;
Person *person3 = [[Person alloc]initWithHeight:170 withAge:23 withName:@"Mike"];
[arrayB addObject:person3];
NSLog(@"arrayB:%p,%@",arrayB,arrayB);
NSLog(@"arrayA:%p,%@",arrayA,arrayA);

創(chuàng)建數(shù)組arrayA的備份數(shù)組arrayC,并且向arrayC中添加對(duì)象person4,輸出arrayC的內(nèi)存地址和數(shù)組中對(duì)象的地址如圖3,可以發(fā)現(xiàn)arrayC和arrayA的地址不同,但是其中的對(duì)象地址卻相同,也就是說(shuō)arrayC數(shù)組中的對(duì)象和arrayA數(shù)組中對(duì)象是同一份,指向相同的內(nèi)存地址。當(dāng)對(duì)數(shù)組arrayA中的person1操作,那么數(shù)組arrayC中的person1也會(huì)相應(yīng)的變化。
NSMutableArray *arrayC = [[NSMutableArray alloc]initWithArray:arrayA];
Person *person4 = [[Person alloc]initWithHeight:175 withAge:24 withName:@"趙子龍"];
[arrayC addObject:person4];
NSLog(@"arrayC:%p,%@",arrayC,arrayC);

有時(shí)候,我們想兩份數(shù)組分別操作時(shí)而互不影響其中的對(duì)象,也就是兩個(gè)數(shù)組位于不同的內(nèi)存地址,并且所含的對(duì)象屬性完全相同但并不是同一個(gè)實(shí)例,那么就需要在深拷貝數(shù)組的同時(shí)深拷貝數(shù)組中的對(duì)象。代碼如下,創(chuàng)建arrayD的同時(shí)拷貝arrayA中的所有對(duì)象,并且向arrayD中添加對(duì)象person5,輸出arrayD的內(nèi)存地址和所含對(duì)象的地址如圖4所示。
NSMutableArray *arrayD = [[NSMutableArray alloc]initWithArray:arrayA copyItems:YES];
Person *person5 = [[Person alloc]initWithHeight:177 withAge:44 withName:@"趙云"];
[arrayD addObject:person5];
NSLog(@"arrayD:%p,%@",arrayD,arrayD);

arrayD的內(nèi)存地址arrayA的內(nèi)存地址不同,而且所含對(duì)象的地址也是不同的,這樣在操作arrayD和arrayA的時(shí)候,兩者是互不影響的。
備注,NSMutableArray *arrayD = [[NSMutableArray alloc]initWithArray:arrayA copyItems:YES];這句代碼的使用需要數(shù)組中的對(duì)象遵循NSCoping和NSMutableCopying協(xié)議,也就是這里的Person類(lèi)重載如下的兩個(gè)方法,否則直接用上面的API會(huì)崩潰。
-(id)copyWithZone:(NSZone *)zone;
-(id)mutableCopyWithZone:(NSZone *)zone;
重載代碼的示例如下:
-(id)copyWithZone:(NSZone *)zone
{
Person *A = [[self class] allocWithZone:zone];
A.age = self.age;
A.height = self.height;
A.name = self.name;
return A;
}