一、要了解淺拷貝與深拷貝,首要的是理解淺拷貝是什麼,深拷貝是什麼。數組
<1>淺拷貝:就至關於retain,只copy了一個對象的引用,和自己是同一個對象,就至關於影子。atom
<2>深拷貝:重新開闢了一塊內存空間,用來存放原來對象裏面的東西,這個時候,copy出來的對象和原來的對象不是同一個對象,他們的內容同樣,就至關於克隆人。spa
<3>拷貝出來的的對象是什麼類型取決於使用什麼拷貝。3d
二、拷貝的用法code
<1>不可變copy拷貝不可變對象(淺拷貝):對象
NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil]; NSArray *array1=[array copy]; NSLog(@"array1=%@",array1); NSLog(@"array=%p,array1=%p",array,array1); NSLog(@"array = %lu ,array1 = %lu",[array retainCount],[array1 retainCount]);
其輸出結果:blog
看輸出結果反饋出:對不可變數組array進行不可變copy時,拷貝出來的array1是跟array同樣的對象且兩個數組的引用計數都+1,至關於對array自己的一個引用而已。內存
<2>不可變copy拷貝可變對象(深拷貝):it
NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil]; NSArray *array=[mArray copy]; NSLog(@"mArray=%p,array=%p",mArray,array); NSLog(@"array=%@",array); NSLog(@"array的類型%@",[array class]); NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);
其輸出結果:io
看輸出結果反饋出:對可變數組mArray進行不可變copy操做,拷貝出來的array數組與mArray數組的內存地址是不同的且兩塊內存地址內容是相同的,而內容是同樣的且引用計數不發生改變,array數組的類型不變依舊是不可變數組。由此能夠得出不可變copy拷貝可變對象是深拷貝。
<3>可變copy拷貝不可變對象(深拷貝):
NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil]; NSMutableArray *mArray=[array mutableCopy]; NSLog(@"-%@",[[array mutableCopy] class]); NSLog(@"array=%p,mArray=%p",array,mArray); NSLog(@"mArray=%@",mArray); NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);
其輸出結果:
看輸出結果反饋出:對不可變數組array進行可變可變copy操做,拷貝出來的mArray數組與array數組的內存地址不一樣且兩塊內存地址內容是相同的,且拷貝出來的對象是可變的,引用計數並無發生改變,由此能夠得出可變copy拷貝不可變對象是深拷貝。
<4>可變copy拷貝可變對象(深拷貝):
NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil]; NSMutableArray *array=[mArray mutableCopy]; NSLog(@"%@",[[mArray mutableCopy] class]); NSLog(@"mArray=%p,array=%p",mArray,array); NSLog(@"array=%@",array); NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);
其輸出結果:
看輸出結果反饋出:對可變數組array進行可變可變copy操做,拷貝出來的array數組與mArray數組的內存地址不一樣且兩塊內存地址內容是相同的,且拷貝出來的對象是可變的,沒有引發引用計數的變化,由此能夠得出可變copy拷貝可變對象是深拷貝。
<5>自定義類的copy:
自定義一個person類
.h文件
#import <Foundation/Foundation.h> //要實現copy必須遵照NSCopying或者NSMutableCopying協議,這裏面有一個必須實現的協議copyWithZone: @interface Person : NSObject<NSCopying> @property(retain,nonatomic)NSString *name; @property(copy,nonatomic)NSArray *array; @property(copy,nonatomic)NSMutableArray *mArray; @end
.m文件
#import "Person.h" @implementation Person -(id)copyWithZone:(NSZone *)zone { Person *pp=[[Person alloc]init]; // NSLog(@"pp=%p",pp); pp.name=self.name; return pp; } @end
在main.m文件中,導入person類頭文件且添加下列代碼
/* 要實現copy必須遵照NSCopying或者NSMutableCopying協議,這裏面有一個必須實現的協議copyWithZone: */ Person *p=[[Person alloc]init]; p.name=@"張三"; Person *p1=[p copy]; NSLog(@"p=%p,p1=%p",p,p1); NSLog(@"p1的名字爲%@",p1.name);
運行結果獲得:
能夠得出:自定義對象進行copy操做獲得的是兩塊補同樣的內存地址,且內容是同樣的。
<6>屬性的copy:
1、copy修飾不可變屬性的時候,就至關於retain
2、copy修飾可變屬性的時候,至關於不可變copy拷貝可變對象。屬於深拷貝,這個時候,屬性和對屬性賦值的對象的內存都須要單獨管理
3、建議對象類型都是用retain