0

For my requirement, I have to go back to my rootviewcontroller (tabbar) but It have many page present on it.

example flow

my tabbar (have 4 tabs each tab has own navigation ) -> push(vc1) -> present nav(vc2) -> push vc3 -> present nav(vc4)

If I want to close all viewcontroller ( vc1 - vc4 ) How to dismiss them by one function ?

1
  • Try this UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil) Commented Jul 20, 2021 at 18:38

2 Answers 2

1

You can use UIViewController.dismiss(animated:completion:) call on the base view controller that started presentation from tab bar (root level).

If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.

Given this hierarchy

my tabbar (have 4 tabs each tab has own navigation ) -> push(vc1) -> present nav(vc2) -> push vc3 -> present nav(vc4)

You can walk back the presentation hierarchy like following -

let vc4Presenter = vc4.navigationController?.presentingViewController

let vc2NavCtrl = (vc4Presenter as? UINavigationController) ?? vc4Presenter?.navigationController
let vc2Presenter = vc2NavCtrl?.presentingViewController

let vc1NavCtrl = (vc2Presenter as? UINavigationController) ?? vc2Presenter?.navigationController
vc2Presenter?.dismiss(animated: true, completion: {
    vc1NavCtrl?.popToRootViewController(animated: false)
})

Above is merely an example of how you can find the correct view controller instance to call dismiss on in the view hierarchy. This is definitely not well suited for dynamic number of presentation layers.

You can -

  1. Write this in a recursive way (so that it keeps looking for presentingViewController until it finds nil for the root level).
  2. Have a convenient reference to tab bar controller throughout the app and call dismiss on it's currently selected view controller (tab).
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @Tarun, This help me a lot. I already created recursive for this one. It's amazing!!
0

If you want go directly to first viewController:

self.popToRootViewController(animated: true)

If you want to see how it is going away one by one

@objc func buttonPressed() {
        
        let viewControllers: [UIViewController] = self.viewControllers

        for aViewController in viewControllers {
            self.popViewController(animated: true)
        }
        
        self.popToRootViewController(animated: true)
    }

2 Comments

This popToRootViewController is only for Navigation right ? If flow be like this root->push(v1)->present(v2) How to dismiss all from v2?
@NawinPoolsawad it should also work for this situation too. Did you tried it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.