如何在执行segue之前执行按钮动画[重复]
Posted
技术标签:
【中文标题】如何在执行segue之前执行按钮动画[重复]【英文标题】:How to perform button animation before performing segue [duplicate] 【发布时间】:2018-12-27 17:05:01 【问题描述】:在我的主屏幕中,我有一个 startGame 按钮,按下该按钮时会触发动画 (sender.pulsate()),然后还会更改 viewController:
@IBAction func newGamePressed(_ sender: UIButton)
currentScore = 0
timeRemaining = 60
visualTime = "01:00"
sender.pulsate()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "firstLevel")
self.present(viewController, animated: false, completion: nil)
但是,新的 viewController 会立即出现,而不是等待脉动动画发生(脉动动画确实有效)。
我知道这与没有自上而下阅读的代码有关,但是我可以添加什么来告诉 xcode 在另一个之前运行一个?
谢谢!
ps。这是相关的脉动代码:
func pulsate()
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.duration = 0.6
pulse.fromValue = 0.95
pulse.toValue = 1.0
pulse.autoreverses = true
pulse.repeatCount = 2
pulse.initialVelocity = 0.5
pulse.damping = 1.0
layer.add(pulse, forKey: nil)
【问题讨论】:
【参考方案1】:您的动画持续时间为0.6
秒。在那之后展示 ViewController
之后异步
您可以为您的 pulsate
方法创建完成,该方法在动画结束后执行
func pulsate(duration: CFTimeInterval, _ completion: @escaping ()->())
...
pulse.duration = duration
...
DispatchQueue.main.asyncAfter(deadline: .now() + duration)
completion()
CATransaction 的完成块
您可以为您的pulsate
方法创建completion
,该方法在您的CAAnimation
结束后执行。为此,您可以使用CATransaction
的完成块
func pulsate(duration: CFTimeInterval, _ completion: @escaping ()->())
CATransaction.begin()
...
pulse.duration = duration
...
CATransaction.setCompletionBlock
completion()
CATransaction.commit()
sender.pulsate(duration: 0.6)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "firstLevel")
self.present(viewController, animated: false, completion: nil)
【讨论】:
感谢这个成功!【参考方案2】:也可以使用performSelector
来实现
@IBAction func didTapButton(_ sender: UIButton)
let animationDuration = 0.6
sender.pulsate(duration:animationDuration)
//Invoke method after particular delay on current thread
self.perform(#selector(navigateToViewController), with: nil, afterDelay: animationDuration)
@objc func navigateToViewController()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "NewViewControllerID") as! NewViewController
self.present(viewController, animated: false, completion: nil)
脉动码
func pulsate(duration: Double)
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.duration = duration
pulse.fromValue = 0.95
pulse.toValue = 1.0
pulse.autoreverses = true
pulse.repeatCount = 2
pulse.initialVelocity = 0.5
pulse.damping = 1.0
layer.add(pulse, forKey: nil)
【讨论】:
【参考方案3】:只需对我们的动画使用完成方法,没有计时器延迟。
func pulsate()
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.duration = 0.6
pulse.fromValue = 0.95
pulse.toValue = 1.0
pulse.autoreverses = true
pulse.repeatCount = 2
pulse.initialVelocity = 0.5
pulse.damping = 1.0
layer.add(pulse, forKey: nil)
CATransaction.setCompletionBlock
print("animation done")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "firstLevel")
self.present(viewController, animated: false, completion: nil)
【讨论】:
请注意,这不起作用,因为他的pulsate
方法在UIButton
上被调用并且按钮不能present
ViewController【参考方案4】:
使用asyncAfter
和[weak self]
的替代方法来删除保留周期,
DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) [weak self] in
self?.present(viewController, animated: false, completion: nil)
【讨论】:
什么是保留周期? 保持对对方对象的强引用,会导致内存泄漏以上是关于如何在执行segue之前执行按钮动画[重复]的主要内容,如果未能解决你的问题,请参考以下文章