1.想讓一個(gè)類實(shí)現(xiàn)copy方法就要遵循NSCopying協(xié)議
如果想讓類實(shí)現(xiàn)copy方法枪狂,就要遵循NSCopying協(xié)議危喉,同時(shí)重寫這個(gè)協(xié)議的唯一一個(gè)方法copyWithZone方法。
-(id)copyWithZone:(NSZone*)zone;
??:其實(shí)我們并不是重寫了copy方法州疾,而是重寫了copyWithZone方法
2.如果想讓一個(gè)類有可變版本和不可變版本就要同時(shí)遵循NSCopying協(xié)議和NSMutableCopying協(xié)議
NSMutableCopying協(xié)議里只有一個(gè)方法:
-(id)mutableCopyWithZone:(NSZone*)zone;
3.可變版本和不可變版本
無論當(dāng)前實(shí)例是否可變辜限,若需獲取其可變版本的拷貝都應(yīng)該調(diào)用mutableCopy方法,如果要獲得不可變版本的拷貝就應(yīng)該調(diào)用copy方法孝治。
[NSMutableArray copy]=>NSArray
[NSArray mutableCopy]=>NSMutableArray
但是這么做是不安全的,比如說一個(gè)類本來是可變的审磁,然后copy之后變成了不可變的谈飒,這個(gè)時(shí)候再去調(diào)用以前的可變類的方法會crash。
4.深拷貝和淺拷貝
??:這里有一個(gè)特別重要的誤區(qū)态蒂,不是說調(diào)用copy方法就是淺拷貝杭措,調(diào)用mutablecopy就是深拷貝,并沒有專門定義深拷貝的協(xié)議钾恢,所以深拷貝方法的實(shí)現(xiàn)是需要自己去確定的手素。
淺拷貝:淺拷貝是對指針的拷貝,對一個(gè)對象進(jìn)行淺拷貝瘩蚪,相當(dāng)于拷貝了一個(gè)指向它的指針泉懦,相當(dāng)于把對象的引用計(jì)數(shù)加1,指針指向的內(nèi)存地址就是原對象的內(nèi)存地址疹瘦。
深拷貝:深拷貝是對值的拷貝崩哩,相當(dāng)于拷貝出了一個(gè)完全新的對象,只是對象的值和原對象的值相等言沐。
非容器對象:
????NSString* string = @"laowang";
? ? NSString* str1 = [string copy];
? ? NSString* str2 = [string mutableCopy];
? ? NSLog(@"string:%p",string);
? ? NSLog(@"str1:%p",str1);//和string是一個(gè)內(nèi)存地址
? ? NSLog(@"str2:%p",str2);//和string是不同的內(nèi)存地址
??打印結(jié)果:
string:0x10265c060邓嘹、str1:0x10265c060、str2:0x7f8b7ae96860
??:對于不可變的非容器對象险胰,copy是淺拷貝汹押,mutableCopy是深拷貝
對于可變的非容器對象,無論是copy還是mutableCopy都是深拷貝起便,拷貝出來的都是新的對象棚贾。
????NSMutableString* mtr = [NSMutableString stringWithFormat:@"laowang"];
????NSString* mtr1 = [mtr copy];
? ? NSString* mtr2 = [mtr mutableCopy];
? ? NSMutableString* mtr3 = [mtr copy];這里這個(gè)mtr3雖然寫的是可變字符串窖维,但是調(diào)用可變字符串的方法appendString程序會崩潰!
? ? NSMutableString* mtr4 = [mtr mutableCopy];
? ? NSLog(@"mtr=%p",mtr);
? ? NSLog(@"mtr1=%p",mtr1);
? ? NSLog(@"mtr2=%p",mtr2);
? ? NSLog(@"mtr3=%p",mtr3);
? ? NSLog(@"mtr4=%p",mtr4);
結(jié)果:mtr=0x7faaf8d1e7c0鸟悴、mtr1=0xa676e61776f616c7陈辱、mtr2=0x7faaf8d1e800
mtr3=0xa676e61776f616c7、mtr4=0x7faaf8d1e840
不可變?nèi)萜鲗ο螅?/b>
? ??NSArray* array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
? ? NSArray* array1 = [array copy];//淺拷貝
? ? NSArray* array2 = [array mutableCopy];//深拷貝
? ? NSLog(@"array = %p",array);
? ? NSLog(@"array1 = %p",array1);
? ? NSLog(@"array2 = %p",array2);
結(jié)論:array = 0x7f8073426bd0细诸、array1 = 0x7f8073426bd0沛贪、array2 = 0x7f8073426c00
??:copy對容器對象本身是淺拷貝,對容器對象內(nèi)對象也是淺拷貝
mutableCopy 對容器對象本身是深拷貝震贵,對容器對象內(nèi)對象也是淺拷貝
可以用一個(gè)圖說明:
可變?nèi)萜鲗ο蟮目截悾?/p>
無論是copy還是mutableCopy對容器對象本身都是深拷貝利赋,但是對于容器對象內(nèi)的每個(gè)對象都是淺拷貝(指針拷貝)
所以說foundation框架里的這些集合類都沒有實(shí)現(xiàn)真正意義上的深拷貝,就是既對集合本身深拷貝猩系,也對集合內(nèi)的每個(gè)對象深拷貝媚送,要想實(shí)現(xiàn)這樣的深拷貝需要我們自己去給類添加深拷貝的實(shí)現(xiàn)方法。
實(shí)現(xiàn)完全深拷貝:
- (instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag;
NSMutableArray *marry1 = [[NSMutableArray alloc] init];
NSMutableString *mstr1 = [[NSMutableString alloc]initWithString:@"value1"];
NSMutableString *mstr2 = [[NSMutableString alloc]initWithString:@"value2"];
[marry1 addObject:mstr1];
[marry1 addObject:mstr2];
NSArray *marray2 = [[NSArray alloc] initWithArray:marry1 copyItems:YES];
marray2里的每一個(gè)元素的內(nèi)存地址和marry1里的都不同寇甸,所以說容器內(nèi)的每個(gè)元素也是深拷貝塘偎。