以前一直對NSCopying和NSMutableCopying兩個類比較陌生恤煞,為了深入理解,做筆記如下,筆記會分一個概述和四個小節(jié)來進行講解:
NSCopying是一個Foundation框架的基本協(xié)議腊徙,所有的NSObject以及其子類都遵守這個協(xié)議酷含。遵守這個協(xié)議的類都需要重寫- (id)copyWithZone:這個方法,區(qū)別在于系統(tǒng)的類會由系統(tǒng)來重寫代理方法哨毁,而自定義的類需要我們手動重寫代理方法枫甲,如果不進行重寫系統(tǒng)會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);
```
打印結果如下:
MasonryTest[1368:150492] 0x10bc34220
MasonryTest[1368:150492] 0x10bc34220
MasonryTest[1368:150492] 0x60800007b300
可以看出strCopy對str進行了指針拷貝,mutableStrCopy對str進行了內(nèi)容话浇。然后我們將strCopy聲明為NSMutableString脏毯,調(diào)用appendString方法:
NSMutableString *mStrCopy = [str copy];
[mStrCopy appendString:@"test"]; // crash
原因在于copy返回的對象是不可變的,強制調(diào)用appendString方法幔崖,在運行時的時候無法再方法列表中找到方法抄沮,所以crash
集合類:
2.不可變的集合類:
NSArray *arr = @[@"zhangsan",@"lisi"];
NSMutableArray *arrCopy = [arr copy];
NSMutableArray *mutableArrCopy = [arr mutableCopy];
NSLog(@"%p",arr);
NSLog(@"%p",arrCopy);
NSLog(@"%p",mutableArrCopy);
運行結果為:
MasonryTest[1502:163348] 0x600000037e80
MasonryTest[1502:163348] 0x600000037e80
MasonryTest[1502:163348] 0x60000004f2d0
由此可見copy對不可變的集合類進行了指針拷貝,mutableCopy對不可變的集合類進行了內(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);
運行結果:
MasonryTest[1544:169111] 0x60800005f5f0
MasonryTest[1544:169111] 0x608000039b80
MasonryTest[1544:169111] 0x608000058fc0
可見可變的集合類進行無論進行copy還是mutableCopy實質上都進行了內(nèi)容拷貝
3.自定義對象:
Person *person = [[Person alloc]init];
Person *personCopy = [person copy]; // crash
Person *personMutableCopy = [person mutableCopy]; // crash
原因是自定義對象沒有實現(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;
}
重寫方法后運行結果為:
MasonryTest[1763:186469] 0x60000000a3c0
MasonryTest[1763:186469] 0x60000000a450
MasonryTest[1763:186469] 0x60000000a480
由此可見無論是copy還是mutableCopy都對自定義對象進行了內(nèi)容拷貝