问题
I am trying to create a subclass of CALayer with a custom index property that I can both animate and change directly in order to display a different picture based on the index.
In the header, I declared:
@property NSUInteger index;
In the implementation, I overrode needDisplayForKey:
+ (BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:@"index"])
return YES;
else
return [super needsDisplayForKey:key];
}
Now, in the display method, I want to display a picture based on the index. However, during an animation, the value of self.index never changes, so I have to query the value of the presentation layer, contrary to the example on Providing CALayer Content by Subclassing:
- (void)display
{
NSUInteger presentationIndex = [(CustomLayer *)[self presentationLayer] index];
self.contents = (id)[[images objectAtIndex:presentationIndex] CGImage];
}
The problem is, if I do that, I cannot set the index value directly outside of an animation, because it will only change the model layer, and the display method explicitly queries the presentation layer.
If I add an initialization method that copies the value of index, it works:
- (id)initWithLayer:(id)layer
{
self = [super initWithLayer:layer];
if (self) {
if ([layer isKindOfClass:[CustomLayer class]])
self.index = [(CustomLayer *)layer index];
}
return self;
}
However, after or before an animation, there is always a 1 image glitch because the presentation or the model value don't match (depending if I set index to the destination value or not).
- Surprisingly, it seems like the
drawInContext:method always has the right value for[self index], but it is not the method I want to use since I just set thecontentproperty with an image. - I get different behaviors depending on the way I implement the
indexproperty. If I use@dynamic index(which works, even though the documentation doesn't say that custom property getters/setters would be dynamically implemented),displayis called every time the value ofindexis changed. If I use@synthesizeor implement a setter,displayis not called, so I would need to changecontentin the setter too. - Should I use an instance variable? Should I use the dynamic implementation? Or should I use
setValue:forKey:instead?
As you can see, I am a bit confused about how to get the result I want, and how to correctly implement a subclass of CALayer with a custom property. Any help, and explanations, would be appreciated!
回答1:
There is an excellent tutorial on the web that explains how to create a custom CALayer subclass with animatable properties. I haven't had occasion to try it yet, but I bookmarked it. Here is the link:
Animating Pie Slices Using a Custom CALayer
It looks like the main tricks are:
Use @dynamic, not @synthesize for the animatable properties of your custom CALayer.
Override actionForKey:, initWithLayer:, and needsDisplayForKey:, and perhaps drawInContext:
来源:https://stackoverflow.com/questions/10387406/how-exactly-to-subclass-calayer-and-use-a-custom-property