在 Swift 中向 UIViewPropertyAnimator 添加完成处理程序
Posted
技术标签:
【中文标题】在 Swift 中向 UIViewPropertyAnimator 添加完成处理程序【英文标题】:Adding a completion handler to UIViewPropertyAnimator in Swift 【发布时间】:2021-05-31 11:04:10 【问题描述】:我正在尝试让属性动画师在呈现视图控制器时启动动画。
现在动画正在播放,但是 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
,但似乎没有任何效果。
【问题讨论】:
为什么将pausesOnCompletion
设置为true?
【参考方案1】:
整个事情看起来设计不正确。
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 中。
【讨论】:
现在完成处理程序工作但动画没有播放(模糊视图突然出现)。你测试过这个吗?有什么建议吗? 必须设置blurView.effect = nil
。现在它完美地工作了。谢谢。【参考方案2】:
问题是您将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 所说,您不应该在 draw
中初始化您的 animator
。同样,如果您确实有使用 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
可以在初始化器中设置。
【讨论】:
以上是关于在 Swift 中向 UIViewPropertyAnimator 添加完成处理程序的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中向 UIViewPropertyAnimator 添加完成处理程序