如何解决在 Swift 中向 UIViewPropertyAnimator 添加完成处理程序
我试图让一个属性动画师在一个视图控制器出现时开始动画。
现在动画正在播放,但是 UIViewPropertyAnimator
没有响应添加到它的完成处理程序。
-
UIVisualEffectView
子类。
import UIKit
final class BlurEffectView: UIVisualEffectView {
deinit {
animator?.stopAnimation(true)
}
override func draw(_ rect: CGRect) {
super.draw(rect)
effect = nil
animator = UIViewPropertyAnimator(duration: 1,curve: .linear) { [uNowned self] in
self.effect = theEffect
}
animator?.pausesOnCompletion = true
}
private let theEffect: UIVisualEffect = UIBlurEffect(style: .regular)
var animator: UIViewPropertyAnimator?
}
- 第一个视图控制器
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func doSomething(_ sender: UIButton) {
let vc = storyboard?.instantiateViewController(identifier: "second") as! SecondVC
vc.modalPresentationStyle = .overFullScreen
present(vc,animated: false) { //vc presentation completion handler
//adding a completion handler to the UIViewPropertyAnimator
vc.blurView.animator?.addCompletion({ (pos) in
print("animation complete") //the problem is that this line isn't executed
})
vc.blurView.animator?.startAnimation()
}
}
}
- 第二个视图控制器
import UIKit
class SecondVC: UIViewController {
@IBOutlet weak var blurView: BlurEffectView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
这里 UIViewPropertyAnimator
完成处理程序是在第二个视图控制器(具有视觉效果视图的控制器)呈现之后添加的。我曾尝试将完成处理程序移动到不同的位置,例如 viewDidLoad
和 viewDidAppear
,但似乎没有任何效果。
解决方法
整个事情似乎设计不正确。
draw(_ rect:)
不是初始化您的动画师*的地方,我对发生的事情的最佳猜测是当您尝试启动它时 vc.blurView.animator?
是 nil
(您确认它不是不是吗?)。
相反,您的视图类可能如下所示**:
final class BlurEffectView: UIVisualEffectView {
func fadeInEffect(_ completion: @escaping () -> Void) {
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.5,delay: 0,options: []) {
self.effect = UIBlurEffect(style: .regular)
} completion: { _ in
completion()
}
}
}
你会像这样执行你的动画:
present(vc,animated: false) { //vc presentation completion handler
vc.blurView.fadeInEffect {
// Completion here
}
}
*draw(_ rect:)
每次让系统知道您需要重绘视图时都会被调用,并且在内部您应该使用 CoreGraphics 来绘制视图的内容,这不是您想要的在这里做。
**由于您没有使用属性动画器的任何更高级的功能,因此似乎没有必要将其存储在 ivar 中。
,问题在于您将 pausesOnCompletion
设置为 true。这会导致不调用完成处理程序。
如果您确实需要将其设置为 true,则需要使用 KVO 来观察 isRunning
属性:
// property of your VC
var ob: NSKeyValueObservation?
...
self.ob?.invalidate()
self.ob = vc.blurView.animator?.observe(\.isRunning,options: [.new],changeHandler: { (animator,change) in
if !(change.newValue!) {
print("completed")
}
})
vc.blurView.animator?.startAnimation()
正如 EmilioPelaez 所说,您不应该在 animator
中初始化您的 draw
。同样,如果您确实有使用 pausesOnCompletion = true
的理由,请将其设置为惰性属性:
lazy var animator: UIViewPropertyAnimator? = {
let anim = UIViewPropertyAnimator(duration: 1,curve: .linear) { [unowned self] in
self.effect = self.theEffect
}
anim.pausesOnCompletion = true
return anim
}()
self.effect = nil
可以在初始化程序中设置。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。