Search code examples
objective-ccore-animationnsview

NSView.animator isAnimating raises error


I have some NSView subclass that I'm animating (changing frame and alpha value). Sometimes I would need to stop the animation, however I'm keep getting error

Here is a code:

[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:1.5f];
[textView.animator setFrame:frame];
[textView.animator setAlphaValue:0.0];
[NSAnimationContext endGrouping];

if ([textView.animator isAnimating]) { // Here the exception is raised
    NSLog(@"%@ is animating!", textView);
}

I am trying to call [textView.animator isAnimating] but that just gives me

Exception detected while handling key input.
*** -[NSProxy doesNotRecognizeSelector:isAnimating] called!

Example project with the code is at https://bitbucket.org/lukaszb/animationartifacts/src/0dc41660f26dd3b629c28bbbda6eb647

I could probably add some isAnimating property to my NSView subclass and set it at animation start and at the completion handler, however that could also lead to some race condition issue I suppose.

Could anyone help me how to detect if a view is being animated?


Solution

  • Neither NSView nor its animator have a property animating, so you cannot just query that value.

    However, as you suggest, you can define your own property for that purpose. The trick is to set it back to NO once the animation is done, which you can do using the completionHandler property on the current animation context:

    [NSAnimationContext beginGrouping];
    [NSAnimationContext currentContext].completionHandler = ^{ self.animating = NO; };
    // ... set up your animation ...
    [NSAnimationContext endGrouping];
    

    Note that the block is called on the main thread (as indicated in the documentation), so it will ensure that the state is consistent as long as you always set the animating property on the main thread. Since you are dealing with UI code, that is probably the case.