Animation 等待UIView动画循环完成的最佳方式是什么?

Animation 等待UIView动画循环完成的最佳方式是什么?,animation,uiview,core-animation,uiviewanimation,catransaction,Animation,Uiview,Core Animation,Uiviewanimation,Catransaction,我正在尝试循环多个ui视图,并对每个视图执行动画,但我想知道所有动画何时完成。动画循环完成后调用函数的最佳方式是什么?或者,有没有办法等到一切都结束了 我尝试使用setAnimationDidStopSelector,但它没有启动。在本例中,我通过让它们淡出然后移除来清除游戏板上的一些“筹码”(NumberedChipView是UIView的一个子类)。在筹码离开棋盘之前,游戏无法继续 [UIView beginAnimations:nil context:nil]; [UIView setA

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

我尝试使用
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:)];

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

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

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

请注意,通过基于索引值增加延迟量,可以使用此索引方法使每个动画在不同的时间开始:

delay = .3 + (0.5 * index);

这就是最终对我有用的东西。我意识到UIView animateWithDuration方法与begin/commit部分没有关联。相反,begin/commit部分标记了一个“隐式”动画操作的区域,因此我可以在动画中设置属性,然后它将被隐式动画化

例如,在下面的动画中,我只是将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方法中,我进行“清理”,并从superview中删除和碎片。这个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];
       }

   }

}

我认为这里的缺点是,完成块是动画发生在一个单独的线程上,因此同时发生。所以,你必须保证延迟变量的原子性。我尝试过类似的方法,但它会挂起。请参阅Apple文档中关于此动画并发性的内容:当然,UIView beginAnimation/Committeanimation方法是较旧的样式,Apple文档中说基于块的方法是首选方法。但我真的不知道如何使基于块的方法在这种情况下工作。只需使用animateWithDuration:delay:options:animations:completion:在for循环中,为每个动画计算不同的延迟值,使它们在不同的时间开始。此外,仅向最终动画添加完成块