简体   繁体   中英

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!

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM