fuz*_*oat 74 iphone cocoa-touch objective-c copywithzone
我试图澄清一些关于实施的问题copyWithZone:,任何人都可以评论以下内容......
// 001: Crime is a subclass of NSObject.
- (id)copyWithZone:(NSZone *)zone {
Crime *newCrime = [[[self class] allocWithZone:zone] init];
if(newCrime) {
[newCrime setMonth:[self month]];
[newCrime setCategory:[self category]];
[newCrime setCoordinate:[self coordinate]];
[newCrime setLocationName:[self locationName]];
[newCrime setTitle:[self title]];
[newCrime setSubtitle:[self subtitle]];
}
return newCrime;
}
// 002: Crime is not a subclass of NSObject.
- (id)copyWithZone:(NSZone *)zone {
Crime *newCrime = [super copyWithZone:zone];
[newCrime setMonth:[self month]];
[newCrime setCategory:[self category]];
[newCrime setCoordinate:[self coordinate]];
[newCrime setLocationName:[self locationName]];
[newCrime setTitle:[self title]];
[newCrime setSubtitle:[self subtitle]];
return newCrime;
}
Run Code Online (Sandbox Code Playgroud)
最好是直接编写类名[[Crime allocWithZone:zone] init]还是应该使用[[[self Class] allocWithZone:zone] init]?
是否可以[self month]用于复制iVars或者我应该直接访问iVars,即_month?
Ton*_*ony 98
您应始终使用[[self class] allocWithZone:zone]以确保使用适当的类创建副本.您为002提供的示例显示了原因:子类将调用[super copyWithZone:zone]并期望获取相应类的实例,而不是超类的实例.
我直接访问ivars,所以我不需要担心稍后可能会添加到属性设置器的任何副作用(例如,生成通知).请记住,子类可以自由地覆盖任何方法.在您的示例中,您每个ivar发送两条额外消息.我会按如下方式实现它:
码:
- (id)copyWithZone:(NSZone *)zone {
Crime *newCrime = [super copyWithZone:zone];
newCrime->_month = [_month copyWithZone:zone];
newCrime->_category = [_category copyWithZone:zone];
// etc...
return newCrime;
}
Run Code Online (Sandbox Code Playgroud)
当然,无论是复制ivars,保留它们,还是仅仅分配它们都应该反映出setter的作用.
copyWithZone:SDK提供的对象的方法的默认复制行为是"浅拷贝".这意味着,如果你调用copyWithZone:的NSString对象,它会创建一个浅表副本,但不深拷贝.浅拷贝和深拷贝之间的区别是:
对象的浅表副本只会复制对原始数组对象的引用,并将它们放入新数组中.
深层复制实际上将复制对象中包含的各个对象.这是通过copyWithZone:在自定义类方法中向每个单独的对象发送消息来完成的.
INSHORT:要获得浅拷贝,您可以调用retain或调用strong所有实例变量.要获得深层复制,请调用copyWithZone:自定义类copyWithZone:实现中的所有实例变量.现在您可以选择.