0
votes

In my project there's a ViewController which contains a few subviews(e.g. buttons). It shows/hides those buttons, always with animation.

It has an interface like this:

@interface MyViewController: UIViewController

- (void)setMyButtonsVisible:(BOOL)visible;

@end

And an implementation looks like this:

- (void)setMyButtonsVisible:(BOOL)visible
{
    if( visible )
    {
        // "show"
        _btn1.hidden = NO;
        _btn2.hidden = NO;
        [UIView animateWithDuration:0.2 animations:^{
            _btn1.alpha = 1.0;
            _btn2.alpha = 1.0;
        }];
    }
    else
    {
        // "hide"
        [UIView animateWithDuration:0.2 animations:^{
            _btn1.alpha = 0.0;
            _btn2.alpha = 0.0;
        } completion:^(BOOL finished) {
            _btn1.hidden = YES;
            _btn2.hidden = YES;
        }];
    }
}

When [_myVC setMyButtonsVisible:NO] is called, and then after some time ( > 0.2s) [_myVC setMyButtonsVisible:YES] is called, everything is OK. However, it setMyButtonsVisible:YES is called immediately after ( < 0.2s) setMyButtonsVisible:NO, the animations overlap and setMyButtonsVisible:NO callback is called the last.

I've tried to change "hide" duration to 0.1, it doesn't help - after "hide(0.1)"+"show(0.2)" calls, "hide" callback is called after the "show" callback and my buttons are not visible.

I've added a quick-fix by caching the visible param and checking in "hide" completion handler if the state should be !visible.

My questions are:

  1. Why the first animation completion handler is called the last if animations overlap?
  2. What are better approahes to discard a previous "overlapping" animation?
1

1 Answers

1
votes

Check the finished flag on completion:

if (finished) {
 _btn1.hidden = YES;
 _btn2.hidden = YES; 
}