1.哪些具体的代码用到了NSCopying协议呢?
- 以NSArray为例:
// 对NSArray进行操作
NSArray *typeArray = @[@"A", @"B", @"C"];
NSArray *copyArray = [typeArray copy]; // 指针拷贝
NSMutableArray *mutableCopyArray = [typeArray mutableCopy];//内容拷贝
//对NSMutableArray进行操作
NSMutableArray *numArray = [NSMutableArray arrayWithObject:@"1",@"2",@"3"];
NSArray *copyArray0 = [numArray copy];//内容拷贝
NSMutableArray *mutableCopyArray0 = [array numArray];//内容拷贝
- 具体解释:
1. 调用copy方法时:就会调用- (id)copyWithZone:(NSZone *)zone,得到不可变的对象,该方法即NSCopying的协议方法
2. 调用mutableCopy方法时:就会调用- (id)mutableCopyWithZone:(NSZone *)zone,得到可变的对象,该方法即NSMutableCopying的协议方法
3. Foundation类已经遵守了两种协议,且实现了copy和mutableCopy方法,因此Foundation对象可以使用这些方法创建不可变对象或可变对象,自定义类时需要遵守协议并且手动实现协议方法
2.进一步了解NSCopying和NSMutableCopying协议
(1)NSCopying:让一个类的对象支持浅拷贝 ; NSMutableCopying:让一个类的对象支持深拷贝
(2)NSCopying中唯一的协议方法:
- NSZone的由来:之前开发程序,会把内存分为不同的“区(zone)”,而对象会创建在某个区里面,现在每个程序都只有一个区:“默认区”,所以zone参数已经没有什么实际意义了
- (id)copyWithZone:(NSZone *)zone
(3)重写该协议:
- 具体重写方式
- (id)copyWithZone:(NSZone *)zone{
PersonModel *model = [[[self class] allocWithZone:zone] init];
model.firstName = self.firstName;
model.lastName = self.lastName;
return model;
}
- 具体说明:一定要通过[self class]方法返回的对象调用allocWithZone:方法。因为指针可能实际指向的是PersonModel的子类。这种情况下,通过调用[self class],就可以返回正确的类的类型对象,且该类直接继承自NSObject,无需调用[super copyWithZone:zone]
3.NSCopying与NSMutableCopying的联系
(1)自定义的对象分为可变与不可变,则同时实现这两个协议
(2)一般情况下,尽量使用浅拷贝
(3)如果你写的对象需要深拷贝,可考虑新增一个专门执行深拷贝的方法
(4)两者的区别如下图
4.常见面试题:定义NSString属性时,是使用copy还是strong,为什么?
@interface Person : NSObject
@property (nonatomic, copy) NSString *familyname;
@property (nonatomic, strong) NSString *nickname;
@end
Person *p1 = [[Person alloc]init];
NSMutableString *familyname = [[NSMutableString alloc]initWithString:@"张三"];
p1.familyname = familyname;
[familyname appendString:@"李四"];
NSLog(@"p1.familyname is %@",p1.familyname); //p1.familyname is 张三
NSMutableString *nickname = [[NSMutableString alloc]initWithString:@"王二"];
p1.nickname = nickname;
[nickname appendString:@"麻子"];
NSLog(@"p1.nickname is %@", p1.nickname);//p1.nickname is 王二麻子
- 总结: 在拷贝对象时,需要注意拷贝执行的是深拷贝还是浅拷贝。
深拷贝的意思就是:在拷贝对象自身时,会将对象的底层数据也进行复制。
浅拷贝是只拷贝容器对象本身,而不拷贝其中数据。Foundation 框架中所有的collection 类在默认情况下都执行浅拷贝。
要点:
- 要点: 若想令自己所写的对象具有拷贝功能,则需实现NSCopying协议。
如果自定义的对象分为可变版本与不可变版本,那么就要同时实现NSCopying与NSMutableCopying协议。
复制对象时需决定采用浅拷贝还是深拷贝,一般情况下应该尽量执行浅拷贝。
如果你所写的对象需要深拷贝,那么可考虑新增一个专门执行深拷贝的方法。