appilis
appilis

Reputation: 13

Resetting the navigation stack on a UITabBarController doesn't work

I'm trying to reset the navigation stack on a subclass of UITabViewController embedded in a UINavigationController but it doesn't work.

My navigation stack, which I create programmatically, is like this:

UINavigationController => ControllerA (a subclass of UIViewController) => ControllerB (a subclass of UIViewController) => ControllerC (a subclass of UITabBarController).

When users press on the "Back" button or swipe back from ControllerC, the app should go back to ControllerA, not ControllerB.

Usually, when I want to reset the navigation stack, I do this in the Controller's viewDidLoad() method:

override func viewDidLoad() {

  super.viewDidLoad()

  // usually work, but not in a subclass of UITabBarController as self.navigationController is nil
  if let navigationController = self.navigationController {

    // keep only the root controller (0) and the current controller
    navigationController.viewControllers = [navigationController.viewControllers[0], self]
  }
}

but this doesn't work in ControllerC (the subclass of UITabViewController) as self.navigationController is nil.

If I do this instead (still in ControllerC's viewDidLoad() method):

/// ControllerC's viewDidLoad
override func viewDidLoad() {

  super.viewDidLoad()

  if let navigationController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {

    // keep only the root controller (0) and the current controller
    navigationController.viewControllers = [navigationController.viewControllers[0], self]
  }
}

This works, but then there is no animation between ControllerB and ControllerC when I do:

controllerB.navigationController?.pushViewController(ControllerC(), animated: true)

I also tried to override ControllerC's viewWillDisappear() method:

/// ControllerC's viewWillDisappear
override func viewWillDisappear(_ animated: Bool) {

  super.viewWillDisappear(animated)

  if self.isMovingFromParent {

    if let navigationController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {

     navigationController.popToRootViewController(animated: true)
  }
}

This works, but ControllerB is briefly visible before ControllerA is shown.

Any help would be greatly appreciated!

Upvotes: 1

Views: 95

Answers (1)

Nick  Burinok
Nick Burinok

Reputation: 81

In the ControllerC instead of trying to override viewWillDisappear() method you can override viewDidAppear() like that:

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if let navC = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
            // keep only the root controller (0) and the current controller
            navC.viewControllers = [navC.viewControllers[0], self]
        }
    }

And ControllerB won’t be briefly visible before ControllerA when you navigate backwards.

Upvotes: 0

Related Questions