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 support its internal bookkeeping.
I set the value of the new property in drawInContext:
but what I find that it is always reset to 0 when the next call is made. Is this so because Core Animation assumes that this property is also for animation, and that it "animates" its value at constant 0 lacking further instructions? In any case, how can I add truly non-animatable properties to subclasses of CALayer
?
I have found a preliminary workaround, which is using a global CGFloat _property
instead of @property (assign) CGFloat property
but would prefer to use normal property syntax.
UPDATE 1
This is how I try to define the property in MyLayer.m
:
@interface MyLayer()
@property (assign) CGFloat property;
@end
And this is how I assign a value to it at the end of drawInContext:
:
self.property = nonZero;
The property is e.g. read at the start of drawInContext:
like so:
NSLog(@"property=%f", self.property);
UPDATE 2
Maybe this it was causes the problem (code inherited from this sample)?
- (id)actionForKey:(NSString *) aKey {
if ([aKey isEqualToString:@"someAnimatableProperty"]) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:aKey];
animation.fromValue = [self.presentationLayer valueForKey:aKey];
return animation;
}
return [super actionForKey:aKey]; // also applies to my "property"
}
To access your standard property from within the drawing method, during an animation, you need to make a few modifications.
Implement initializer
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:Therefore, you need to implement
-initWithLayer:
and use it to copy manually the value of your property on the new instance, like this:Access properties through model layer
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 setself.myProperty
from within-drawInContext:
, when the method is called on one of the presentation copies, you get an exception:Instead of setting
self.myProperty
, you should writeas
modelLayer
will instead refer to the originalMyCustomLayer
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 propertypresentationLayer
, that instead returns the current (copy of the) layer being displayed.