以前一直对NSCopying和NSMutableCopying两个类比较陌生,为了深入理解,做笔记如下,笔记会分一个概述和四个小节来进行讲解:
NSCopying是一个Foundation框架的基本协议,所有的NSObject以及其子类都遵守这个协议。遵守这个协议的类都需要重写- (id)copyWithZone:这个方法,区别在于系统的类会由系统来重写代理方法,而自定义的类需要我们手动重写代理方法,如果不进行重写系统会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进行了内容。然后我们将strCopy声明为NSMutableString,调用appendString方法:
NSMutableString *mStrCopy = [str copy];
[mStrCopy appendString:@"test"]; // crash
原因在于copy返回的对象是不可变的,强制调用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对不可变的集合类进行了内容拷贝
可变的集合类:
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实质上都进行了内容拷贝
3.自定义对象:
Person *person = [[Person alloc]init];
Person *personCopy = [person copy]; // crash
Person *personMutableCopy = [person mutableCopy]; // crash
原因是自定义对象没有实现- (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都对自定义对象进行了内容拷贝