开发者

copyWithZone setting instance variables?

开发者 https://www.devze.com 2022-12-15 10:00 出处:网络
Is the copyWithZone (See Below) correct, particularly the bit where I use the setters to populate the instance variables of the new object?

Is the copyWithZone (See Below) correct, particularly the bit where I use the setters to populate the instance variables of the new object?

@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:

Is this a better way?

-(id) copyWithZone: (NSZone *) zone {
    Planet *newPlanet = [[[se开发者_运维技巧lf class] allocWithZone:zone] init];
    [newPlanet setName:[self name]];
    [newPlanet setType:[self type]];
    [newPlanet setMass:[self mass]];
    [newPlanet setIndex:[self index]];
    return(newPlanet);
}

many thanks

gary


(Assuming deep copy is what you want) for the copy we want to make, use copyWithZone: for object instance variables and simply set primitive instance variables using =.

- (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;
}

But notice how properties of the same class as self and copy must be set without copyWithZone:. Otherwise, these objects will call this copyWithZone again, and will try to set their myClassProperties using copyWithZone as well. This triggers an unwanted infinite loop. (Also, you could call allocWithZone: instead of alloc: but I'm pretty sure alloc: calls allocWithZone: anyway)

There are some cases where using = to deep copy object properties of the same class might not be the thing you want to do, but in ALL CASES (as far as I'm aware) deepcopying object properties of the same class with copyWithZone: or anything that calls copyWithZone: will result in an infinite loop.


Whether it's an unwanted copy or not is for you to decide. The reason to synthesize accessors with the copy qualifier is to be sure of the ownership of those objects.

Keep in mind though, that immutable objects like an NSNumber or an NSString won't actually duplicate their storage when they're sent a -copy message, they'll just increase their retain counts.


Have you read this guide ? If so, you have to choose whether you want a shallow or a deep copy. For shallow copies, you can share values: this is a typical approach when implementing a NSCell sublcass that share an NSImage instance.

As I don't know the context, I will say that your implementation seems correct.

0

精彩评论

暂无评论...
验证码 换一张
取 消