[SOLVED] How to use source (not presenting) in animationController (UIViewControllerTransitioningDelegate)?

Issue

I’m making a custom Transition Manager. It conforms to the protocols UIViewControllerAnimatedTransitioning & UIViewControllerTransitioningDelegate.

When presenting from RocketsVC to RocketDetailsVC, func is called animationController(for Presented presented: UIViewController, presenting: UIViewController, source: UIViewController), the following types are passed there:

  • presented: RocketDetailsViewController
  • presenting: MainTabBarController (Error is here)
  • source: RocketsViewController

This functions are declared in TransitionManager.swift:

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    type = .presentation
    return self // TransitionManager
}

And then animateTransition method is called…

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    guard let fromViewController = transitionContext.viewController(forKey: .from) as? TransitionManagerProtocol,
        let toViewController = transitionContext.viewController(forKey: .to) as? TransitionManagerProtocol

…with zero effect, because MainTabBarController does not conform to TransitionManagerProtocol.

If I build a project without MainTabBarController (rootVC is RocketsVC), then everything works as it should.

What should I do to make the transition work? I’m sinning on MainTabBarController, but maybe there is a way to somehow pass to animationController method source instead of presenting?

Full code is in my GitHub

TransitionManager.swift
RocketsViewController.swift
MainTabBarController.swift

Solution

The solution I’ve found after long hours:

private var fromVC: UIViewController?
private var toVC: UIViewController?

...

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    type = .presentation
    fromVC = source
    toVC = presented
    return self
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    type = .dismissal
    toVC = fromVC // last `fromVC` is now `toVC`
    fromVC = dismissed // and now we set this to fromVC
    return self
}

And:

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    guard let fromViewController = fromVC as? TransitionManagerProtocol,
          let toViewController = toVC as? TransitionManagerProtocol
    else {
        transitionContext.completeTransition(false)
        return
    }
    ...

Answered By – Klim Postironin

Answer Checked By – Willingham (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *