Dismissing multiple modal view controllers at once?

Viewed 10851

So have a stack with three view controllers where A is root, B is first modal view controller and C is third modal vc. I would like to go from C to A at once. I have tried this solution to dismiss.It does work but not in a correct way. That is when the last view controller is dismissed it will breifly show the second view controller before the first is shown. What I'm looking for is a way to get from the third vc to the first in one nice animation without noticing the second view. Any help on this is greatly appriciated.

7 Answers

For anyone looking for a work around you can do this:

  1. Cover everything with a snapshot of the window.
  2. Dismiss both view controllers without animation.
  3. Present a copy of the snapshot in another view controller without animation.
  4. Remove the snapshot covering the window.
  5. Dismiss the snapshot view controller with animation.

Here's the code:

let window = UIApplication.shared.keyWindow!
let snapshot = window.snapshotView(afterScreenUpdates: false)!
window.addSubview(snapshot)

let baseViewController = self.presentingViewController!.presentingViewController!

baseViewController.dismiss(animated: false) {
    let snapshotCopy = snapshot.snapshotView(afterScreenUpdates: false)!
    let snapshotViewController = UIViewController()
    snapshotViewController.view.addSubview(snapshotCopy)

    baseViewController.present(snapshotViewController, animated: false) {
        snapshot.removeFromSuperview()
        baseViewController.dismiss(animated: true, completion: nil)
    }
}

Here's a simple way in you can "dismiss to home":

    var vc: UIViewController = self
    while vc.presentingViewController != nil {
        vc = vc.presentingViewController!
    }
    vc.dismiss(animated: true, completion: nil)

You can recursively find presentingViewController to get to the root:

extension UIViewController {
    
    private func _rootPresentingViewController(_ vc:UIViewController, depth:Int) -> UIViewController? {
        guard let parentPresenter = vc.presentingViewController else {
            return vc
        }
        if depth > 20 {
            return nil
        }
        return _rootPresentingViewController(parentPresenter, depth: depth + 1)
    }
    
    @objc
    func rootPresentingViewController() -> UIViewController? {
        return _rootPresentingViewController(self, depth: 0)
    }
    
}
Related