I have defined a subclass of CALayer
with an animatable property as discussed here. I would now like to add another (non-animatable) property to that layer to suppo
To access your standard property from within the drawing method, during an animation, you need to make a few modifications.
When CoreAnimation performs your animation, it creates shadow copies of your layer, and each copy will be rendered in a different frame. To create such copies, it calls -initWithLayer:
.
From Apple's documentation:
If you are implementing a custom layer subclass, you can override this method and use it to copy the values of instance variables into the new object. Subclasses should always invoke the superclass implementation.
Therefore, you need to implement -initWithLayer:
and use it to copy manually the value of your property on the new instance, like this:
- (id)initWithLayer:(id)layer
{
if ((self = [super initWithLayer:layer])) {
// Check if it's the right class before casting
if ([layer isKindOfClass:[MyCustomLayer class]]) {
// Copy the value of "myProperty" over from the other layer
self.myProperty = ((MyCustomLayer *)layer).myProperty;
}
}
return self;
}
The copy, anyway, takes place before the animation starts: you can see this by adding a NSLog
call to -initWithLayer:
. So as far as CoreAnimation knows, your property will always be zero. Moreover, the copies it creates are readonly, if you try to set self.myProperty
from within -drawInContext:
, when the method is called on one of the presentation copies, you get an exception:
*** Terminating app due to uncaught exception 'CALayerReadOnly', reason:
'attempting to modify read-only layer <MyLayer: 0x8e94010>' ***
Instead of setting self.myProperty
, you should write
self.modelLayer.myProperty = 42.0f
as modelLayer
will instead refer to the original MyCustomLayer
instance, and all the presentation copies share the same model. Note that you must do this also when you read the variable, not only when you set it. For completeness, one should mention as well the property presentationLayer
, that instead returns the current (copy of the) layer being displayed.