I have a CALayer with a custom animation on it, working via an @NSManaged property, and overriding:
- class func defaultValue(forKey key: String) -> Any?
- class func needsDisplay(forKey key: String) -> Bool
- func action(forKey key: String) -> CAAction?
- func display()
However, I sometimes want to bypass the animation and have the property immediately step to the new value. In my CALayer sub-class I tried this:
@NSManaged private var radius: CGFloat
func animate(to radius: CGFloat) {
    self.radius = radius
}
func step(to radius: CGFloat) {
    // Inspired by https://stackoverflow.com/a/34941743
    CATransaction.begin()
    CATransaction.setDisableActions(true)   // Prevents animation occurring
    self.radius = radius
    CATransaction.commit()
    setNeedsDisplay()                       // Has no effect
}
When animate(to:) is called, display() is called repeatedly and my custom drawing code can do it's thing. When step(to:) is called, the CATransaction code does prevent an animation from occurring, but no drawing is ever performed at all.
I can get it to behave as desired, but it feels quite hacky:
func step(to radius: CGFloat) {
    // func action(forKey key: String) -> CAAction? uses .animationDuration
    // when constructing a CABasicAnimation
    let duration = animationDuration
    defer { animationDuration = duration }
    animationDuration = 0
    self.radius = radius
}
What is the correct method to give the caller the ability to choose whether the property animates from one value to the next, or steps immediately? A subsequent change to radius should respect the previous value, whether it was stepped or animated to.
 
    