0

如何在使用块结构的情况下为 UIView 设置动画?我只需要强制动画在调用后立即执行,并且我没有将程序的其余部分放在基于代码结构的完成块中的奢侈。

具体来说,现在,这就是正在发生的事情

while (actionsRemaining)
{
   [self performDesiredAnimation];
   ....computation ....
   [barWidget decreaseValueTo:resultOfComputation];
}

当我运行此代码时,所有 [performDesiredAnimation] 动画同时发生,大约 10 个 barWidgets 全部同时减少。我想要的是:

performDesiredAnimation1 --> barWidget 减少 --> performDesiredAnimation2 --> barWidget 减少 --> performDesiredAnimation3 --> barWidget 减少 --> ...但是未知次数。

我不知道有多少次,因为如果 barWidget 减少超过某个值,动作将从 actionsRemaining 中删除,即循环数将取决于中间计算。

更简单地说,当我只调用循环的一次迭代时,我想要的结果与我现在看到的结果相同

[self performDesiredAnimation];
....computation ....
[barWidget decreaseValueTo:resultOfComputation];

,然后是第二次迭代,然后是第三次,所有这些都是孤立的。现在,如果我注释掉循环,动画看起来还不错,但是当我将循环保留在那里时,它们都会一起粉碎。我只希望动画从迭代到迭代顺序执行,而不是一次全部执行。

4

2 回答 2

2

块不是导致您出现问题的原因。我认为您的问题是您的“for循环中的动画”结构。

您需要将动画操作保存在堆栈中,当一个完成时,将下一个从堆栈中弹出并执行。或者,如果需要继续,请检查动画的完成块,如果需要,请再次调用动画方法。就像是:

-(void)performAnimation
{
    [UIView animateWithDuration:0.25 
                     animations:^{[self performDesiredAnimations];}
                     completion:^(BOOL finished){
                                // It's not clear what your computations are or if they take any significant time
                                CGFloat result = [self doComputations];
                                [barWidget decreaseValueTo:resultOfComputation]
                                if (needToPerformAnotherSet) // Work this out however you need to
                                {
                                    [self performAnimation];
                                }
                            };
}
于 2013-11-12T12:32:07.060 回答
1

你可以这样做:

// Start the work in a background thread.

dispatch_async(dispatch_get_global_queue(0, 0), ^{

    while (actionsRemaining) {

        // Do your calculation in the background if your code will allow you to

        [self performDesiredAnimation];
        ....computation ....

        // Back to the main thread for a chunk of code

        dispatch_sync(dispatch_get_main_queue(), ^{

            // Or do it here if not

            [self performDesiredAnimation];
            ....computation ....

            // Finally, update your widget.

            [barWidget decreaseValueTo:resultOfComputation];
        }
    }
} 

}

由于您的循环在每次迭代时进入异步后台循环,因此应用程序的主运行循环将有机会使用您在同步块中设置的值更新您的 UI。

于 2013-11-12T12:47:54.273 回答