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



有没有一种方法可以中断动画,而不是"取消"(快退)它们,而是"快进"它们,迫使它们的完成闭包比原计划提前运行?

背景:

在 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()

有谁知道这是否可能?

谢谢。

代码的问题在于您正在检查完成闭包的第一个参数。这指示动画是否完成。只有当这是真的时,你才会跑updateMainDisplay()

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

要解决此问题,只需删除if $0语句。

现在 Xcode 将显示警告,因为您没有使用闭包的第一个参数。要消除此警告,只需在关闭的开头放置_ in

{ _ in
// some code
}

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

最新更新