1

CALayer seems to have almost everything required to add properties to a layer at runtime, without subclassing, using a delegate and/or the layer's actions property. However, one thing I have not figured out is how to trigger display updates when one of these dynamic properties changes in an animation.

I know how do this in a custom subclass of CALayer: simply define the properties in the subclass, mark them @dynamic, and override needsDisplayForKey: and return YES for the custom properties. Then display will be invoked during animations, which, by default, will even trigger a call to the layer delegate's drawLayer:inContent: method, if present (though it's of questionable usefulness, given that you've already got this subclass where you can implement drawInContext:). However, I am trying to see if this is possible without subclassing CALayer.

I can get as far as supporting updates outside of animations using only a layer delegate, by installing a CAAction in the layer's actions property, or implementing actionForLayer:forKey: in the layer delegate, and having that action send a setNeedsDisplay message to the layer. However, actionForKey: is apparently not called during an animation (makes sense, since it is used to trigger implicit animations), and there is no equivalent to needsDisplayForKey: in the layer delegate protocol, that I can see.

So, is there any way to tell CALayer to call display for custom properties besides the above? Or is it not possible to implement animatable custom layer properties in a layer delegate alone? It seems like Apple would prefer one to use delegation when possible, but without a way to refresh the layer contents during an animation, the delegate interface is incomplete. Any suggestions?

big_m
  • 1,408
  • 1
  • 12
  • 24
  • Let me ask you this: how would you mark this property as `@dynamic`, which you know you need to do? – matt Jul 15 '15 at 16:40
  • @matt: If you're not subclassing, you can't, of course. But it doesn't seem to matter for anything else; all `@dynamic` does is tell the compiler that some accessor methods will be generated at runtime. But even without accessors, CALayer lets you add virtual properties using `valueForKey:` and `setValue:forKey:`. Like I said, it all works except for triggering `display` updates during animations. Maybe it's not supposed to work, but, man, they came so close! – big_m Jul 15 '15 at 17:45
  • Well, you don't actually need `@dynamic` as long as you don't try to call this thing via implicit property animation - if you are going to make a CABasicAnimation with a key path, then `needsDisplayForKey` (and a drawing implementation) is _all_ you need. So surely you can do it that way? – matt Jul 15 '15 at 17:53
  • 1
    @matt, yes, I can implement `needsDisplayForKey:` _in a CALayer subclass_, but I don't see how to provide the equivalent using only a layer delegate. That's what I'm trying to figure out (if it's possible). – big_m Jul 15 '15 at 18:19
  • Aha. No, I don't see how to do that either. Fascinating idea, but clearly they didn't build that into the delegate model. You could file a feature request, but don't hold your breath: I doubt they want to mess with this, since the entire house of cards depends on it. – matt Jul 15 '15 at 18:24
  • No, and any future addition would not be backward compatible, so it's not much help. I may make a little CALayer subclass (or monkey-patch `needsDisplayForKey:`) to add a new delegate method for my own use, but for the time being, the subclass implementation will do. Thanks for your input, @matt! – big_m Jul 15 '15 at 18:40
  • Damn! Why didn't I find your question earlier. I tried the same thing: https://stackoverflow.com/q/62421716/ and spent significant time with it. – Bruno Bieri Jun 17 '20 at 15:04

0 Answers0