I have 2 root view controllers that I need to animate (slide up/fade) between.
When I press a button on viewControllerA, viewControllerB should load itself in the background and set itself as the root view controller. When that is ready, viewControllerA should slide up and at the same time gradually fade out, revealing viewControllerB. When the animation completes, viewControllerA should be removed from the hierarchy. I set viewcontrollerB as the root before the animation starts so the user can swipe around on viewControllerB as viewControllerA slides up.
viewControllerA will sometimes have a video playing or other animations going on and I do not want them to stop during the transition. viewControllerA should be fully removed from the hierarchy after the animation completes.
After many many hours I have come up with this:
private func setNewRootViewController(_ viewController: UIViewController) {
DispatchQueue.main.async {
UIView.animate(withDuration: 0.5, animations: {
// Slide up and fade out the current viewController (vcA)
self.view.alpha = 0
self.view.transform = CGAffineTransform(translationX: 0, y: - self.view.frame.height)
}) { _ in
// Remove the current viewController from the parent view controller
self.removeFromParent()
// Set the new viewController (vcB) as the root view controller
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = viewController
}
// Animate the appearance of the new viewController (vcB)
UIView.animate(withDuration: 0.5) {
viewController.view.alpha = 1
}
}
}
It slides up viewControllerA and fades it out but it only reveals a black background. After it finishes, the black screen suddenly turns into viewControllerB. I feel like I am super close but am tearing my hair out and it’s late here. I have searched all through stack over flow and by testing several ideas is how I wrote the above. Please help
2
Answers
The "black screen suddenly turns into viewControllerB" because the new controller hasn’t been added yet as
viewController.view.alpha = 1
will execute beforeappDelegate.window?.rootViewController = viewController
.I suggest you create a new
UIViewController
that acts as a container for the controllers in question. To switch between them:Instead of replacing the root view controller, you could create a custom container view controller for viewControllerA and viewControllerB:
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html
Something like this: