Software Stewardship
Overriding NSCopying:copyWithZone

In the wild I sometimes see the following as implementation of NSCopying:copyWithZone:

-(id)copyWithZone:(NSZone*)zone
{
    MYClass* copy = [MYClass new];
    copy.property1 = self.property1;
    ...
    copy.propertyN = self.propertyN;
    return copy;
}

This is wrong as accessing the copy and the original objects through . during the copying process itself must be avoided as each of those . may actually introduce side-effects. We are copying data here and the resulting copied object should faithfully reflect the state of the original object, not invoke methods on either of these objects.

The correct way to approach this is to skip original object’s getters and copied object’s setters:

-(id)copyWithZone:(NSZone*)zone
{
    MYClass* copy = [MYClass new];
    copy->_property1 = self->_property1;
    ...
    copy->_propertyN = self->_propertyN;
    return copy;
}

(above assuming that the underlying data members were syntesized in the standard way)

We often forget, through Objective-C compiler “magic”, that we are working with pointers and that the good, old -> operator is still there, alive and well.

Btw, when working in C++ I often wish that . operator was overridable as that would make proxying so much easier. But then if both -> and . are overridable you could loose the connection to the actual underlying object. Objective-C goes the other way: it’s the compiler that in a way overrides the . operator giving it a special meaning, while -> operator still does what it always did in C.


Last modified on 2014-07-15