问题描述
试图了解CoreAnimation和完成处理程序。
为什么这段代码一次发生,而不是在5.0秒内发生?
我试图让它以5秒的时间运行6次,每次持续30秒,并且每5秒打印一次“完整”。
func animateBox() {
UIView.animate(withDuration: 5.0,delay: 0.0,options: [],animations: {
self.myBox.layer.borderColor = self.getRandom()
},completion: {finished in
print("complete")
})
}
@objc func buttonTapped() {
for _ in 1...6 {
animateBox()
print("animate")
}
}
解决方法
for _ in 1...6 {
会立即执行,因此animateBox
在瞬间被调用了6次,一次又一次。
您想要做的是在上一个动画完成时间(在动画完成时调用)的内部 中调用每个动画块。像这样:
UIView.animate(withDuration: 5.0,delay: 0.0,options: [],animations: {
self.myBox.layer.borderColor = self.getRandom()
},completion: { finished in
print("complete")
UIView.animate(withDuration: 5.0,animations: {
self.myBox.layer.borderColor = self.getRandom()
},completion: { finished in
print("complete")
UIView.animate(withDuration: 5.0,animations: {
self.myBox.layer.borderColor = self.getRandom()
},completion: { finished in
print("complete")
...
})
})
})
但这将导致巨大的完成金字塔……相反,请尝试使用animateKeyframes
:
let totalDuration = CGFloat(30)
let relativeIndividualDuration = CGFloat(1) / CGFloat(6)
UIView.animateKeyframes(withDuration: totalDuration,delay: 0,options: .calculationModeCubic,animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0,relativeDuration: relativeIndividualDuration) {
self.myBox.layer.borderColor = self.getRandom()
}
UIView.addKeyframe(withRelativeStartTime: relativeIndividualDuration,relativeDuration: relativeIndividualDuration) {
self.myBox.layer.borderColor = self.getRandom()
}
UIView.addKeyframe(withRelativeStartTime: relativeIndividualDuration * 2,relativeDuration: relativeIndividualDuration) {
self.myBox.layer.borderColor = self.getRandom()
}
...
})
,
您可以对动画进行排序的另一种方法是使用延迟参数,并在第一步之后为每一步添加一个延迟:
func animateBox(step: Int) {
let duration = 5.0
UIView.animate(withDuration: duration,delay: duration * Double(step),completion: {finished in
print("complete")
})
}
@objc func buttonTapped() {
for index in 0...5 {
animateBox(step: index)
print("animating step \(index)")
}
}
(请注意,我将您的循环更改为从 0...5 运行,因此 delay =step * duration
将从 0 开始。)