NSCopying
is not always as simple to implement as you would think. Apple has a good write-up discussing the complexities, but let me elaborate. Forgive some ranting digressions. It’s important to know how to work around the problems I’m going to discuss, but it’s also important to understand how insane it is to have to work around this issue.
First, there’s the fairly obvious problem of deep versus shallow copies. If object foo
has an instance variable *bar
, should a copy of foo
have a second pointer to bar
, or should it have its own copy of whatever bar
points to? There is no way to answer this question generally; it depends on the nature of the objects.
Most of the time, this can be dealt with fairly easily by implementing the accessors with the correct behavior (retain versus copy), and you wind up with a copyWithZone:
like this:
- (id)copyWithZone:(NSZone *)zone
{
Product *copy = [[[self class] allocWithZone: zone] init];
[copy setProductName:[self productName]];
return copy;
}
That works really well as long as your superclass doesn’t implement NSCopying
, but if it does, you may not have enough information or access to cleanly copy it. Now you would think this would be easy:
- (id)copyWithZone:(NSZone *)zone
{
Product *copy = [super copy];
[copy setProductName:[self productName]];
return copy;
}
But that may or may not work. If super
implements -copyWithZone:
as described above, then all is fine. But what if your superclass uses NSCopyObject()
? Things go badly, and in ways very difficult to understand and debug.