copyWithZone设置实例变量?

时间:2010-01-06 12:26:58

标签: objective-c

copyWithZone(见下文)是否正确,特别是我使用setter来填充新对象的实例变量的位?

@interface Planet : NSObject <NSCopying>
{
    NSString *name;
    NSString *type;
    NSNumber *mass;
    int index;
}
@property(copy) NSString *name;
@property(copy) NSString *type;
@property(retain) NSNumber *mass;
@property(assign) int index;
-(void)display;
@end

-(id) copyWithZone: (NSZone *) zone {
    Planet *newPlanet = [[Planet allocWithZone:zone] init];
    NSLog(@"_copy: %@", [newPlanet self]);
    [newPlanet setName:name];
    [newPlanet setType:type];
    [newPlanet setMass:mass];
    [newPlanet setIndex:index];
    return(newPlanet);
}

EDIT_001:

这是一种更好的方法吗?

-(id) copyWithZone: (NSZone *) zone {
    Planet *newPlanet = [[[self class] allocWithZone:zone] init];
    [newPlanet setName:[self name]];
    [newPlanet setType:[self type]];
    [newPlanet setMass:[self mass]];
    [newPlanet setIndex:[self index]];
    return(newPlanet);
}
非常感谢

加里

3 个答案:

答案 0 :(得分:6)

对于我们想要制作的副本,

(假设你需要深拷贝),使用copyWithZone:用于对象实例变量,只需使用=设置原始实例变量。

- (id)copyWithZone:(NSZone *)zone
{
    MyClass *copy = [[MyClass alloc] init];

    // deep copying object properties
    copy.objectPropertyOne = [[self.objectPropertyOne copyWithZone:zone] autorelease];
    copy.objectPropertyTwo = [[self.objectPropertyTwo copyWithZone:zone] autorelease];
                  ...
    copy.objectPropertyLast = [[self.objectPropertyLast copyWithZone:zone] autorelease];

    // deep copying primitive properties
    copy.primitivePropertyOne = self.primitivePropertyOne
    copy.primitivePropertyTwo = self.primitivePropertyTwo
                  ...
    copy.primitivePropertyLast = self.primitivePropertyLast

    // deep copying object properties that are of type MyClass
    copy.myClassPropertyOne = self.myClassPropertyOne
    copy.myClassPropertyTwo = self.myClassPropertyTwo
                  ...
    copy.myClassPropertyLast = self.myClassPropertyLast


    return copy;
}

但请注意,如果没有copyWithZone,必须设置与self和copy相同的类的属性:否则,这些对象将再次调用此copyWithZone,并将尝试使用copyWithZone设置其myClassProperties。这会触发不必要的无限循环。 (另外,你可以调用allocWithZone:而不是alloc:但我很确定alloc:调用allocWithZone:无论如何)

在某些情况下,使用=来深度复制同一个类的对象属性可能不是你想要做的事情,但在所有情况下(据我所知)深度复制同一个类的对象属性copyWithZone:或任何调用copyWithZone:会导致无限循环。

答案 1 :(得分:3)

是否是不需要的副本供您决定。使用复制限定符合成访问器的原因是为了确保这些对象的所有权。

请记住,NSNumber或NSString等不可变对象在发送-copy消息时实际上不会复制其存储,它们只会增加其保留计数。

答案 2 :(得分:3)

您是否阅读过this guide?如果是这样,您必须选择是要还是浅拷贝还是深拷贝。对于浅层副本,您可以共享值:这是实现共享NSCell实例的NSImage sublcass时的典型方法。

由于我不知道上下文,我会说你的实现似乎是正确的。