views:

27

answers:

1

I'm a little confused on the correct way to make my class support NSCopy mechanics and I'm hoping someone can help clear things up for me.

The big question is this: If my class is mostly immutatble except for a collections property, when I'm implementing the 'copyWithZone' method through NSCopy inheritance, do I need to do the version where I'm returning a self that had a retain called on it like this:

- (id)copyWithZone:(NSZone *)zone 
{
     return [self retain];
}

or do I need to do the other version that takes in to consider the policies used by NSCopyObject as outlined in the Memory Management programming guide published by Apple? (I've read a number of posts about how NSCopyObject is dangerous so one has to be careful with their implementations).

- (id)copyWithZone:(NSZone *)zone
{
    NSCell *cellCopy = NSCopyObject(self, 0, zone);
    /* Assume that other initialization takes place here. */
    cellCopy->image = nil;
    [cellCopy setImage:[self image]];
    return cellCopy;
}

My class has ivars are a mix of primitive types, object types and an NSArray collection. I'm intending the class to be semi-immutable in the sense that clients cannot modify any of the intrinsic properties after the class was created initially but at some point the client will receive additional related data that needs to be appended to the class. Additionally, when clients are holding on to an instance, they should have their own copy instead of sharing it so it is a deep copy instance as opposed to a shallow copy.

The code:

@interface MySampleClass : NSObject {
NSString *myName;
NSString *myTitle;
BOOL     isAFlag;

NSArray *aListOfProperites; // collection holds objects of another class named 'MySampleProperty'
}

@property (nonatomic, copy, readonly) NSString *myName;
@property (nonatomic, copy, readonly) NSString *myTitle;
@property (nonatomic, readonly) BOOL isAFlag;

@property (nonatomic, copy, readonly) NSArray *aListOfProperties;

-(id)initWithNameTitleAndFlag:(NSString *)aName title:(NSString *)aTitle flag:(BOOL)aFlag;

-(void)addProperty:(MySampleProperty *)aProperty;
@end

@implementation MySampleClass

-(id)initWithNameTitleAndFlag:(NSString *)aName title:(NSString *)aTitle flag:(BOOL)aFlag
{
    self = [super init];
    if (nil != self)
    {
       [self setMyName:aName];
       [self setMyTitle:aTitle];
       [self setAFlag:aFlag];
    }
    return self;
}

// all of my object setters do a 'copy' instead of retain or assign
-(void)setMyName:(NSString *)aNewName
{
if (aNewName != myName) 
{
     [myName release];
     myName = [aNewName copy];
}
}
- (id)copyWithZone:(NSZone *)zone
{
// do I do a simple retain on the object or follow NSCopyObject policies?
}

@end
A: 

If your class was totally immutable, I would suggest a shallow copy. However, because it isn't, you're going to have to do a deep copy in order to avoid bugs (if anything makes a shallow copy of your class, expecting a deep copy, and then changes it, the original object will change as well, when it doesn't seem like it should). Do a deep copy.

itaiferber
Doing the deep copy makes sense. So what is the right way to implement 'copyWithZone'?
Abel Vita
You can go about doing it like this: http://pastie.org/1241957 (this code is untested, but it should work - run tests on your own to confirm).
itaiferber
Abel, if my response has sufficiently answered your question, don't forget to mark it as the answer! Thanks... ;)
itaiferber