迅捷4-segue动画完成后,如何在目标视图控制器中运行代码?

Mic*_*Hsu 2 ios uistoryboardsegue swift

所以我有2个视图控制器,我想从视图控制器1到带有自定义动画的视图控制器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)
Run Code Online (Sandbox Code Playgroud)

在调用performSegue()之前,我先运行了它,然后它起作用了。但是我想做的是在视图控制器2的代码中,我想在segue动画完成后(在0.5秒后)运行某些内容。我的视图控制器不是导航控制器的一部分,因此本文无济于事。我也希望我的代码在目标视图控制器中,但是本文源视图控制器中有它,因此也无济于事。

我已经尝试过测试viewDidLoad()viewDidAppear(),但是它们都在滑动动画完成之前运行。请帮忙,谢谢!

Rob*_*Rob 5

当您正确设置过渡viewDidAppear动画时,动画完成后会被调用。见定制的过渡动画视图控制器编程指南适用于iOS上的正确方法的说明,自定义两种显示控制器之间的过渡。

如该指南所述,当您要自定义模式转换时,应指定一个modalPresentationStyleof .custom,然后指定一个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
    }

    ...

}
Run Code Online (Sandbox Code Playgroud)

并且,在其中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)
    }
}
Run Code Online (Sandbox Code Playgroud)

演示控制器的全部工作是指定完成过渡后应从视图层次结构中删除演示者的视图(这是经验法则,除非演示视图是半透明的或不覆盖整个屏幕):

class PresentationController: UIPresentationController {
    override var shouldRemovePresentersView: Bool { return true }
}
Run Code Online (Sandbox Code Playgroud)

动画师指定动画的持续时间和特定细节:

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)
            })
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,可以执行所需的任何动画,但希望您能掌握基本的想法。最重要的是,目标视图控制器应该指定它transitioningDelegate,然后您就可以进行标准的模态演示(通过present或通过showsegue进行),并且将自定义过渡动画,并在viewDidAppear完成动画后调用目标的动画。