为什么 [UIView animate] 的完成处理程序以错误的顺序调用?

Why are completion handlers of [UIView animate] called in a wrong order?

在我的项目中有一个 ViewController,其中包含一些子视图(例如按钮)。 它 shows/hides 那些按钮,总是带有动画。

它有这样的界面:

@interface MyViewController: UIViewController

- (void)setMyButtonsVisible:(BOOL)visible;

@end

实现如下所示:

- (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;
        }];
    }
}

调用[_myVC setMyButtonsVisible:NO]时,过一段时间(>0.2s)再调用[_myVC setMyButtonsVisible:YES],一切正常。 但是,它 setMyButtonsVisible:YES 在 ( < 0.2s) setMyButtonsVisible:NO 之后立即被调用 ,动画重叠并且 setMyButtonsVisible:NO 回调被调用为最后一个。

我尝试将“隐藏”持续时间更改为 0.1,但没有帮助 - 在“隐藏(0.1)”+“显示(0.2)”调用后,“隐藏”回调在“显示”之后调用" 回调和我的按钮不可见。

我添加了一个快速修复方法,方法是缓存 visible 参数并在状态应为 !visible 时检查“隐藏”完成处理程序。

我的问题是:

  1. 如果动画重叠,为什么第一个动画完成处理程序被调用为最后一个?
  2. 丢弃以前的“重叠”动画的更好方法是什么?

完成时检查 finished 标志:

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