【问题标题】:What is the best way to wait for a loop of UIView animations to finish?等待 UIView 动画循环完成的最佳方法是什么?
【发布时间】:2012-05-16 05:12:43
【问题描述】:

我正在尝试遍历多个 UIViews 并在每个上执行动画,但我想知道所有动画何时完成。动画循环完成后调用函数的最佳方法是什么?或者,有没有办法等到一切都完成?

我尝试使用setAnimationDidStopSelector,但它没有触发。在这种情况下,我通过让它们淡出然后被移除来清除游戏板上的一些“筹码”(NumberedChipView 是 UIView 的子类)。在筹码离开棋盘之前,游戏无法继续。

[UIView beginAnimations:nil context:nil]; 
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop)]; 

// clear chips 
for (HexagonalTile *aTile in tilesToClear) {

    NumberedChipView *chipView = [self chipViewForColumn:aTile.column andRow:aTile.row];

    [UIView animateWithDuration:0.5 delay:0.3 options:UIViewAnimationCurveLinear animations:^{
        chipView.alpha = 0.0; 
    } 
        completion:^(BOOL finished){

         if (finished) {

             [chipView removeFromSuperview]; 
             [self.chipViews removeObject:chipView];

         }
     }]; 
}

[UIView commitAnimations]; 

我也尝试了CATransaction 无济于事:

[CATransaction begin];  

[CATransaction setCompletionBlock:^{
    [self animationFinished]; 
}];  

// clear chips 
for (HexagonalTile *aTile in tilesToClear) {

    NumberedChipView *chipView = [self chipViewForColumn:aTile.column andRow:aTile.row];

    [UIView animateWithDuration:0.5 delay:0.3 options:UIViewAnimationCurveLinear animations:^{
        chipView.alpha = 0.0; 
    } 
        completion:^(BOOL finished){

         if (finished) {

             [chipView removeFromSuperview]; 
             [self.chipViews removeObject:chipView];

             //NSLog(@"clearing finished"); 
         }
     }]; 
}

[CATransaction commit]; 

更新:

我现在可以触发选择器,但它不会等待动画循环完成。

[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:)];

【问题讨论】:

    标签: animation uiview core-animation uiviewanimation catransaction


    【解决方案1】:

    您的 for 循环以相同的延迟和持续时间触发所有动画,因此它们将同时开始和结束。

    您的完成方法将为您的每个动画调用一次。

    您可以稍微重写代码以在进入循环之前将计数器设置为零,并在每一步之后将其递增。当索引小于数组计数时,传递一个 nil 完成块。一旦索引 == 数组计数,您就位于最后一项,因此请传入一个完成块,其中包含您想要在最后一个动画完成后调用的代码。

    请注意,您可以使用这种索引方法使每个动画在不同的时间开始,方法是根据索引值增加延迟量:

    delay = .3 + (0.5 * index);
    

    【讨论】:

    • 我认为这里的缺点是完成块是动画发生在单独的线程上,因此同时发生。所以,你必须保证延迟变量的原子性。我试过这样的东西,它会挂起。
    • 查看有关此动画并发的 Apple 文档:developer.apple.com/library/ios/#documentation/windowsviews/…
    • 当然 UIView beginAnimation/commitAnimation 方法是较旧的风格,Apple 文档说基于块的方法是首选。但我真的不知道如何使基于块的方法在这种情况下起作用。
    • 只需使用 animateWithDuration:delay:options:animations:completion: 并在您的 for 循环中,为每个动画计算不同的延迟值,以便它们各自在不同的时间开始。也只在最终动画中添加一个完成块
    【解决方案2】:

    这就是最终对我有用的东西。我意识到 UIView animateWithDuration 方法没有与开始/提交部分相关联。相反,开始/提交部分标记了“隐式”动画操作的区域,所以我可以只设置动画中的属性,它会被隐式动画。

    例如,在下面的动画中,我简单地将chipView 的alpha 属性设置为“0.0”,并且chipView(一个UIView)隐式动画消失。

    [UIView beginAnimations:@"tilescleared" context:nil]; 
    [UIView setAnimationDelegate: self];
    [UIView setAnimationDelay:0.3]; 
    [UIView setAnimationDuration:0.5]; 
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; 
    
    for (HexagonalTile *aTile in tilesToClear) {
    
        NumberedChipView *chipView = [self chipViewForColumn:aTile.column andRow:aTile.row];
    
        chipView.alpha = 0.0; 
    
    }
    
    [UIView commitAnimations];
    

    然后,在我的 animationDidStop 方法中,我执行“清理”并从超级视图中移除和筹码。这个 animationDidStop 方法只有在循环中的所有 chipView 动画都完成时才会被触发,这是我试图弄清楚的棘手问题。

    - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context 
    {
    
        if ([animationID isEqualToString:@"tilescleared"]
                      && [finished boolValue]) {
    
           for (HexagonalTile *aTile in self.animationInfo.tilesToClear) {
    
               NumberedChipView *chipView = [self chipViewForColumn:aTile.column andRow:aTile.row];
    
               [chipView removeFromSuperview]; 
               [self.chipViews removeObject:chipView];
           }
    
       }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-24
      • 2016-06-03
      • 2018-02-08
      相关资源
      最近更新 更多