Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if NSAnimationContext runAnimationGroup cancelled or succeeded

I'm animating a view (by revealing it) after which I need to post a notification (once the animation completes). However the way the app's designed, there's another notification sent out when the view is hidden (via animation). So essentially I have a 'showView' and a 'hideView' method. Each do something like so:

    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
      [context setDuration: 0.25];

      [[myView animator] setAlphaValue: 0];
    } completionHandler:^{
       // post notification now
    }];

The problem is that in another thread in the background, I have a periodic timer which performs a 'sanity check' to see if the view needs to be hidden if it's not needed. It's an aggressive approach but necessary as many components of the app respond to different events and scenarios. Due to this I at times get a 'race condition' where the user has clicked to 'showView' but at the same time one of our threads feel the view should be immediately hidden.

When both post a notification on the main thread, the app hangs indefinitely in a SpinLock. I could completely avoid this situation if I was able to figure out if the animation block above was 'cancelled' (i.e. another animation block executed on the same view). In such situations I would not post the notification, which would then not force a check.

Long story short: I need to be able to check if the 'completionHandler' was called after animation successfully ended or if it was cancelled. I know in iOS this is possible but I can't find any way to do this in OS X. Please help.

like image 507
strange Avatar asked Sep 12 '13 19:09

strange


1 Answers

I encountered a similar problem. I solved it by using a currentAnimationUUID instance variable.

NSUUID *animationUUID = [[NSUUID alloc] init];
self.currentAnimationUUID = animationUUID;

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
    // set properties to animate
} completionHandler:^{
    BOOL isCancelled = ![self.currentAnimationUUID isEqual:animationUUID];
    if (isCancelled) {
        return;
    }

    self.currentAnimationUUID = nil;

    // do stuff
}];

Swift version:

let animationUUID = UUID()
currentAnimationUUID = animationUUID

NSAnimationContext.runAnimationGroup({ context in
    // set properties to animate
}, completionHandler: {
    let isCancelled = self.currentAnimationUUID != animationUUID
    guard !isCancelled else {
        return
    }

    self.currentAnimationUUID = nil

    // do stuff
})
like image 180
fumoboy007 Avatar answered Nov 17 '22 04:11

fumoboy007