swift 4 - segue 动画完成后如何在目标视图控制器中运行代码?
Posted
技术标签:
【中文标题】swift 4 - segue 动画完成后如何在目标视图控制器中运行代码?【英文标题】:swift 4 - how do I run code in the destination view controller AFTER the segue animation is finished? 【发布时间】:2018-04-22 16:14:08 【问题描述】:所以我有 2 个视图控制器,我想通过自定义动画从 view controller 1 到 view controller 2。这是我的自定义动画的代码:
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
self.view.window?.layer.add(transition, forKey: nil)
我在调用 performSegue() 之前运行它,它可以工作。但我想做的是在 view controller 2 的代码中,我想在 segue 动画完成后运行一些东西(所以在 0.5 秒后)。我的视图控制器不是导航控制器的一部分,所以this post 没有帮助。我还希望我的代码位于 目标视图控制器 中,但 this post 将它放在 源视图控制器 中,所以这也无济于事。
我尝试过测试viewDidLoad()
和viewDidAppear()
,但它们都在滑动动画完成之前运行。请帮忙,谢谢!
【问题讨论】:
CATransaction.setCompletionBlock(completion) 顺便说一句,如果你想要实现的只是一个推弹式导航,但没有导航栏,你显然可以考虑只使用导航控制器,但指定它的导航栏应该是隐藏... 【参考方案1】:当你正确地为你的过渡设置动画时,viewDidAppear
将在动画完成时被调用。请参阅 ios 视图控制器编程指南中的Customizing Transition Animations 了解有关自定义两个视图控制器之间转换的正确方法的说明。
正如该指南所说,当您想要自定义模态转换时,您应该指定 .custom
的 modalPresentationStyle
,然后指定将提供的 transitioningDelegate
:
例如,目标视图控制器会指定它将执行自定义转换:
class ViewController: UIViewController
// if storyboards, override `init(coder:)`; if NIBs or programmatically
// created view controllers, override the appropriate `init` method.
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
transitioningDelegate = self
modalPresentationStyle = .custom
...
并且,在其UIViewControllerTransitioningDelegate
中,它出售了演示控制器和动画控制器:
extension ViewController: UIViewControllerTransitioningDelegate
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
return TransitionAnimator(operation: .present)
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
return TransitionAnimator(operation: .dismiss)
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController?
return PresentationController(presentedViewController: presented, presenting: presenting)
演示控制器所做的只是指定演示者的视图应该在转换完成时从视图层次结构中删除(这是经验法则,除非演示视图是半透明的或不覆盖整个屏幕):
class PresentationController: UIPresentationController
override var shouldRemovePresentersView: Bool return true
动画师指定动画的持续时间和特定细节:
class TransitionAnimator: NSObject
enum TransitionOperation
case present
case dismiss
private let operation: TransitionOperation
init(operation: TransitionOperation)
self.operation = operation
super.init()
extension TransitionAnimator: UIViewControllerAnimatedTransitioning
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
return 2.0
func animateTransition(using context: UIViewControllerContextTransitioning)
let toVC = context.viewController(forKey: .to)!
let fromVC = context.viewController(forKey: .from)!
let container = context.containerView
let frame = fromVC.view.frame
let rightFrame = CGRect(origin: CGPoint(x: frame.origin.x + frame.width, y: frame.origin.y), size: frame.size)
let leftFrame = CGRect(origin: CGPoint(x: frame.origin.x - frame.width, y: frame.origin.y), size: frame.size)
switch operation
case .present:
toVC.view.frame = rightFrame
container.addSubview(toVC.view)
UIView.animate(withDuration: transitionDuration(using: context), animations:
toVC.view.frame = frame
fromVC.view.frame = leftFrame
, completion: finished in
fromVC.view.frame = frame
context.completeTransition(!context.transitionWasCancelled)
)
case .dismiss:
toVC.view.frame = leftFrame
container.addSubview(toVC.view)
UIView.animate(withDuration: transitionDuration(using: context), animations:
toVC.view.frame = frame
fromVC.view.frame = rightFrame
, completion: finished in
fromVC.view.frame = frame
context.completeTransition(!context.transitionWasCancelled)
)
显然,你可以做任何你想做的动画,但希望你能得到基本的想法。底线,目标视图控制器应该指定它的transitioningDelegate
,然后你可以做一个标准的模态演示(通过present
或show
或只是一个segue),你的过渡动画将被定制,你的目的地的@动画完成后会调用 987654339@。
【讨论】:
这适用于 segues 吗? Apple Documentation 暗示这应该在UIStoryboardSegue
的子类中完成。以上是关于swift 4 - segue 动画完成后如何在目标视图控制器中运行代码?的主要内容,如果未能解决你的问题,请参考以下文章