【问题标题】:Sequential iOS animation *without* blocks?连续的iOS动画*没有*块?
【发布时间】:2013-11-12 07:48:57
【问题描述】:

如何在不使用块结构的情况下为 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];

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

【问题讨论】:

  • 建议使用块,因为它将在另一个线程上执行。 developer.apple.com/library/ios/documentation/windowsviews/…
  • this question中总是有超级老式的开始和提交动画风格
  • 我知道,但我无法将我的动画代码转换成块。一方面,其中一个动画小部件具有我无法访问和修改的动画代码。其次,我自己的动画发生在一个for循环中,我不能轻易地使用块结构来告诉它执行下一个动画,因为它发生在下一次迭代中。
  • “我没有根据代码结构将程序的其余部分放在完成块中的奢侈。”我不明白你这是什么意思。你到底想达到什么目的?使用积木有什么不同?
  • 请记住,您可以从块内部调用“自己”的方法。

标签: ios objective-c animation


【解决方案1】:

块不是导致问题的原因。我认为您的问题是您的“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];
                                }
                            };
}

【讨论】:

  • 谢谢,jrturton。因此,从您的代码(我将要尝试)看来,动画和完成块似乎不需要紧紧地围绕动画本身绑定,对吗?例如,performDesiredAnimations、needToPerformAnotherSet 等中可能会进行一堆中间计算,只要我要分离的动画在动画块内的某个位置,它就会在完成运行之前完成?跨度>
  • 刚试过。虽然动画似乎是按顺序发生的,但持续时间似乎并不正确。我将它设置为像 2.0 和 3.0 一样,它仍然会发生相当棒的事情。
  • 在动画完成之前,上面的代码不会执行完成块中的内容 - 所以无论持续时间设置为什么。如果您在 performDesiredAnimations 中进行计算,那么它们将立即完成,但在执行完成块时结果可能不可用,或者可能已经更改。您需要清楚自己正在使用动画和计算做什么。
  • "performDesiredAnimations" 是一个简单的 ImageView.transform = CGAffineTransformMakeTranslation,由 [UIView beginAnimations] 和 [UIView commitAnimations] 预订,但我还将转换持续时间设置为 1.0 秒。同样,在 [barWidget reductionValueTo:] 中,该动画的持续时间也被硬连线为 3.0 秒,硬编码到小部件 reductionValueTo 调用中。 animateWithDuration:XXX 是否会覆盖所有这些内部动画持续时间?
  • 对于前者,不要从动画块中调用动画。我认为会发生的是动画块将立即返回。如果您从动画块中调用它,则不需要开始/提交。
【解决方案2】:

你可以这样做:

// 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。

【讨论】:

    猜你喜欢
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多