了解UIView.animate以及完成闭包的工作原理

时间:2018-04-13 07:22:08

标签: ios swift animation closures completion

是否有办法以不“取消”(倒带)它们的方式中断动画,而是“快进”它们迫使它们的完成闭包比原计划更早地运行?

背景:

在IOS中,可以“为持续时间的视图设置动画”并包含完成闭包...使用UIView的静态方法animate(),如下所示:

class func animate(withDuration: TimeInterval, animations: () -> Void, completion: ((Bool) -> Void)? = nil)

现实生活中的示例可能如下所示 EXHIBIT-A

// assume we have a UILabel named 'bigLabel'

func animationWeNeedToDo() {

            UIView.animate(withDuration: 1, animations: {
                self.bigLabel.alpha = 0
            }, completion: {
                if $0 {
                    UIView.animate(withDuration: 1, animations: {
                        self.bigLabel.center.x -= 20
                    }, completion: {
                        if $0 {
                            self.updateMainDisplay()
                        }
                    }) }
            })
        }

所以我们有一个UILabel, bigLabel ,我们首先动画为“淡出”,然后我们在第一个完成之前链接到另一个动画,然后又在完成第二,我们运行所有重要的函数updateMainDisplay()。

但是这个简单的例子可能会更复杂,涉及更多的观点。 updateMainDisplay()执行可能是必要的。 ;)

updateMainDisplay()函数非常重要,因为它会“重置”所有视图,将应用程序恢复到与应用程序最初启动时类似的中性状态......有点“重新校准”所有内容。

Anyhoo,麻烦的是,如果用户做了类似的事情,比如早点按下主页按钮或者进行新的活动(模态,如设置......然后回来),则在动画发生时,它永远不会完成... 所以updateMainDisplay()没有被执行! ......事情变得复杂和讨厌。

那么,如何处理这个问题?

似乎需要在“onPause()”中完成某些事情(我知道这不是Android)...就像确保取消动画并执行updateMainDisplay()一样。

但是为了做到这一点,你必须在“onPause()”方法中检查所有类型的布尔状态。如果有办法保证动画完成,我更喜欢。

所以,再一次,我认为如果有一种方法不取消动画,而是“强制立即完成”所有动画,那将是非常棒的。

这是伪代码......但是有办法做这样的事情:

var myAnimation = (animation) { // EXHIBIT-A from above } 

myAnimation.execute()

// if needed:

myAnimation.forceCompletionNow()

有人知道这是否可能?

感谢。

1 个答案:

答案 0 :(得分:1)

您的代码存在的问题是您正在检查完成闭包的第一个参数。这表明动画是否结束。如果确实如此,您只运行updateMainDisplay()

事实上,即使动画没有完成,也会调用完成处理程序 告诉它如果动画没有完成就什么都不做。

要解决此问题,请删除if $0声明。

现在Xcode会显示一个警告,因为你没有使用闭包的第一个参数。要使这个警告保持沉默,只需将_ in放在关闭的开头:

{ _ in
    // some code
}

您可以尝试的另一件事是CABasicAnimation,它不会实际更改视图的属性。它使CALayer s动画化。如果以某种方式再次更新视图,视图将在动画之前返回其原始状态。您似乎想在动画结束后重置所有内容,因此这可能适合您。