以前一直對(duì)NSCopying和NSMutableCopying兩個(gè)類比較陌生,為了深入理解,做筆記如下,筆記會(huì)分一個(gè)概述和四個(gè)小節(jié)來(lái)進(jìn)行講解:
NSCopying是一個(gè)Foundation框架的基本協(xié)議,所有的NSObject以及其子類都遵守這個(gè)協(xié)議。遵守這個(gè)協(xié)議的類都需要重寫- (id)copyWithZone:這個(gè)方法,區(qū)別在于系統(tǒng)的類會(huì)由系統(tǒng)來(lái)重寫代理方法,而自定義的類需要我們手動(dòng)重寫代理方法,如果不進(jìn)行重寫系統(tǒng)會(huì)crash掉。NSMutableCopying與NSCopying類似,需要重寫- (id)mutableCopyWithZone:。
1.非集合類:
```objc
NSString *str = @"test";
NSString *strCopy = [str copy];
NSMutableString *mutableStrCopy = [str mutableCopy];
NSLog(@"%p",str);
NSLog(@"%p",strCopy);
NSLog(@"%p",mutableStrCopy);
```
打印結(jié)果如下:
MasonryTest[1368:150492] 0x10bc34220
MasonryTest[1368:150492] 0x10bc34220
MasonryTest[1368:150492] 0x60800007b300
可以看出strCopy對(duì)str進(jìn)行了指針拷貝,mutableStrCopy對(duì)str進(jìn)行了內(nèi)容。然后我們將strCopy聲明為NSMutableString,調(diào)用appendString方法:
NSMutableString *mStrCopy = [str copy];
[mStrCopy appendString:@"test"]; // crash
原因在于copy返回的對(duì)象是不可變的,強(qiáng)制調(diào)用appendString方法,在運(yùn)行時(shí)的時(shí)候無(wú)法再方法列表中找到方法,所以crash
集合類:
2.不可變的集合類:
NSArray *arr = @[@"zhangsan",@"lisi"];
NSMutableArray *arrCopy = [arr copy];
NSMutableArray *mutableArrCopy = [arr mutableCopy];
NSLog(@"%p",arr);
NSLog(@"%p",arrCopy);
NSLog(@"%p",mutableArrCopy);
運(yùn)行結(jié)果為:
MasonryTest[1502:163348] 0x600000037e80
MasonryTest[1502:163348] 0x600000037e80
MasonryTest[1502:163348] 0x60000004f2d0
由此可見(jiàn)copy對(duì)不可變的集合類進(jìn)行了指針拷貝,mutableCopy對(duì)不可變的集合類進(jìn)行了內(nèi)容拷貝
可變的集合類:
NSMutableArray *arr = [[NSMutableArray alloc]initWithArray:@[@"zhangshan",@"lisi"]];
NSArray *arrCopy = [arr copy];
NSMutableArray *mutableArrCopy = [arr mutableCopy];
NSLog(@"%p",arr);
NSLog(@"%p",arrCopy);
NSLog(@"%p",mutableArrCopy);
運(yùn)行結(jié)果:
MasonryTest[1544:169111] 0x60800005f5f0
MasonryTest[1544:169111] 0x608000039b80
MasonryTest[1544:169111] 0x608000058fc0
可見(jiàn)可變的集合類進(jìn)行無(wú)論進(jìn)行copy還是mutableCopy實(shí)質(zhì)上都進(jìn)行了內(nèi)容拷貝
3.自定義對(duì)象:
Person *person = [[Person alloc]init];
Person *personCopy = [person copy]; // crash
Person *personMutableCopy = [person mutableCopy]; // crash
原因是自定義對(duì)象沒(méi)有實(shí)現(xiàn)- (id)copyWithZone:和- (id)mutableCopyWithZone:方法
-
(id)copyWithZone:(NSZone *)zone {
Person *person = [[[self class] allocWithZone:zone] init];
return person;
} -
(id)mutableCopyWithZone:(NSZone *)zone{
Person *person = [[[self class] allocWithZone:zone] init];
return person;
}
重寫方法后運(yùn)行結(jié)果為:
MasonryTest[1763:186469] 0x60000000a3c0
MasonryTest[1763:186469] 0x60000000a450
MasonryTest[1763:186469] 0x60000000a480
由此可見(jiàn)無(wú)論是copy還是mutableCopy都對(duì)自定義對(duì)象進(jìn)行了內(nèi)容拷貝