首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现copyWithZone时的最佳实践:

实现copyWithZone时的最佳实践:
EN

Stack Overflow用户
提问于 2012-03-28 12:07:37
回答 4查看 49.1K关注 0票数 79

我想澄清一下关于实现copyWithZone:的几件事,有谁能评论一下.

代码语言:javascript
复制
// 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中:

[[[self Class] allocWithZone:zone] init]

  • Is

  • 是最好直接写类名[[Crime allocWithZone:zone] init]还是应该使用[[Crime allocWithZone:zone] init]它可以使用[self month]复制iVars还是应该直接访问iVars,即_month
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-03-28 13:02:25

  1. 您应该始终使用[[self class] allocWithZone:zone]来确保使用适当的类创建副本。您给出的002示例确切地说明了为什么:子类将调用[super copyWithZone:zone],并期望得到适当类的实例,而不是超类的实例。
  2. I直接访问ivars,因此我不需要担心稍后可能给属性设置器添加的任何副作用(例如,生成通知)。请记住,子类可以重写任何方法。在您的示例中,您将向每个ivar发送两条额外的消息。我将按以下方式实现它:

代码:

代码语言:javascript
复制
- (id)copyWithZone:(NSZone *)zone {
    Crime *newCrime = [super copyWithZone:zone];
    newCrime->_month = [_month copyWithZone:zone];
    newCrime->_category = [_category copyWithZone:zone];
    // etc...
    return newCrime;
}

当然,不管你是复制象牙,保留它们,还是仅仅分配它们,都应该反映出设置者所做的事情。

票数 103
EN

Stack Overflow用户

发布于 2015-04-15 15:06:51

使用SDK提供的对象的copyWithZone:方法的默认复制行为是“浅拷贝”。这意味着如果在copyWithZone:对象上调用NSString,它将创建一个浅拷贝,而不是深拷贝。浅拷贝和深拷贝的区别是:

对象的浅拷贝将只复制对原始数组的对象的引用,并将它们放置到新数组中。

深度复制将实际复制包含在对象中的各个对象。这是通过在自定义类方法中向每个单独的对象发送copyWithZone:消息来完成的。

简而言之:要获得浅拷贝,您可以在所有实例变量上调用retainstrong。要获得深度复制,您可以对自定义类copyWithZone:实现中的所有实例变量调用copyWithZone:。现在你可以选择了。

票数 6
EN

Stack Overflow用户

发布于 2017-08-08 03:18:16

那么这个实现深度复制的呢:

代码语言:javascript
复制
/// Class Foo has two properties: month and category
- (id)copyWithZone:(NSZone *zone) {
    Foo *newFoo;
    if ([self.superclass instancesRespondToSelector:@selector(copyWithZone:)]) {
        newFoo = [super copyWithZone:zone];
    } else {
        newFoo = [[self.class allocWithZone:zone] init];
    }
    newFoo->_month = [_month copyWithZone:zone];
    newFoo->_category = [_category copyWithZone:zone];
    return newFoo;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9907154

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档