我正在努力弄清楚我脑海中关于实现 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;
}

在 001 中:
  • 最好直接写类名 [[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 的作用。

    关于iphone - 实现 copyWithZone : 时的最佳实践,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9907154/

    10-13 03:51