我正在努力澄清一些关于实现 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;
}
类名最好直接写[[Crime allocWithZone:zone] init]
还是应该使用[[[self Class] allocWithZone:zone] init]
?
可以使用 [self month]
来复制 iVar 还是我应该直接访问 iVar,即 _month
?
最佳答案
您应该始终使用 [[self class] allocWithZone:zone]
来确保使用适当的类创建副本。您为 002 提供的示例确切说明了原因:子类将调用 [super copyWithZone:zone]
并期望返回适当类的实例,而不是父类(super class)的实例。
我直接访问 ivars,所以我不需要担心我以后可能会添加到属性 setter (例如,生成通知)的任何副作用。请记住,子类可以自由地覆盖任何方法。在您的示例中,您为每个 ivar 发送两条额外的消息。我将按如下方式实现:
代码:
- (id)copyWithZone:(NSZone *)zone {
Crime *newCrime = [super copyWithZone:zone];
newCrime->_month = [_month copyWithZone:zone];
newCrime->_category = [_category copyWithZone:zone];
// etc...
return newCrime;
}
当然,无论您是复制 ivars、保留它们,还是仅仅分配它们,都应该反射(reflect) setter 所做的事情。
https://stackoverflow.com/questions/9907154/