我想在表视图单元格被选中时执行一些动画。由于某些原因,完成块(completion block)过早地被调用了。即使将持续时间设置为10秒,完成块也会立即被调用。
[UIView animateWithDuration:10.0 animations:^{ message.frame = newFrame;} completion:^(BOOL finished) { NSLog(@"DONE???");}];
任何想法为什么会发生这种情况?谢谢。我想在表视图单元格被选中时执行一些动画。由于某些原因,完成块(completion block)过早地被调用了。即使将持续时间设置为10秒,完成块也会立即被调用。
[UIView animateWithDuration:10.0 animations:^{ message.frame = newFrame;} completion:^(BOOL finished) { NSLog(@"DONE???");}];
任何想法为什么会发生这种情况?谢谢。根据UIView文档:
completion
一个在动画序列结束时被执行的块对象。这个块没有返回值,并且需要一个布尔类型的参数,指示动画是否在调用完成处理程序之前实际完成。如果动画的持续时间为0,则在下一个运行循环周期的开头执行此块。该参数可以为NULL。
这意味着不能保证代码仅在动画完成时执行。我建议您检查“finished”参数作为执行的条件。
true
,而且无论我将持续时间设置多长,完成块都会立即调用。 - MikeG是的,之所以被称为“太早”,是因为它在某种程度上被打断了。可能是由于模态展示过渡或其他一些原因。根据您的需要,以下可能是您喜欢的解决方案。我们通过手动延迟执行动画代码来避免冲突,如下所示:
// To get this in Xcode very easily start typing, "dispatch_aft..."
// Note the "0.2". This ensures the outstanding animation gets completed before we start ours
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1.0 delay:0 options:0 animations:^{
// Your animation code
} completion:^(BOOL finished) {
// Your completion code
}];
});
如果动画没有效果,例如将视图的 alpha 设置为其已经具有的值,则完成可以提前调用。
为了帮助大家,我把这个问题发在这里。我的情况是使用了一个 keyframe
动画,但完成块立即被调用了。请注意以下概念:
duration: 动画的总持续时间,以秒为单位。如果您指定负值或0,则更改将立即进行且无需动画。
frameStartTime: 指定动画开始的时间。此值必须在0到1的范围内,其中0表示动画的开始,1表示动画的结束。例如,对于持续时间为两秒的动画,指定开始时间为0.5会导致动画在整个动画开始后一秒开始执行。
frameDuration: 动画到指定值的持续时间。此值必须在0到1的范围内,并表示相对于整个动画长度的时间量。如果指定值为0,则动画块中设置的任何属性会立即更新到指定的开始时间。如果指定非零值,则属性会在该时间段内进行动画处理。例如,对于持续时间为两秒的动画,指定持续时间为0.5会导致动画持续时间为一秒。
任何一个错误的设置都会干扰完成调用的时间。
init
方法中执行,那就太早了。应该在viewDidLoad
或类似的方法中,在控件创建完成后执行。您还可以检查finished
参数。 - Rob