Jay Savsani
Jay Savsani

Reputation: 329

swift navigation controller return nil after changing rootviewcontroller

I'm trying to change rootViewController of my app and it works perfectly. However after changing rootViewController my navigationController returns nil.Because of this even my simple code of pushing any new controller self.navigationController.pushViewController is not working.

Before that I want to explain why I want to change my rootViewController. I've login page(which is initial view controller) and after successful login user will be redirected to UITabBarController (3 tabs). Now I want to change rootViewController to this UITabBarController, which I did successfully with following code.

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let destVC = self.storyboard?.instantiateViewController(withIdentifier: "home_view")
    let rootViewController = appDelegate.window?.rootViewController as! UINavigationController
    appDelegate.window?.rootViewController = destVC

Now after changing rootViewController my all 3 tabs and their respective view controllers are working perfect. But in one of my view controller I've button and on click of that button I want to push new controller to user. Now here I'm facing issues of nil returning navigation view controller.

    let destVC = self.storyboard?.instantiateViewController(withIdentifier: "menu_items_view") as! MenuItems
    self.navigationController?.pushViewController(destVC, animated: true)

When I use simple above code nothing happens. All I was able to debug was my self.navigationController returns nil. Can anyone explain what's my mistake in flow?

enter image description here

Upvotes: 2

Views: 5361

Answers (2)

Gulfam Khan
Gulfam Khan

Reputation: 1089

The answer is very simple, just put your "destVC" inside of a UINavigationController like this:

As of iOS 13 keyWindow is deprecated, we need to write some code to get that, I made an extension on UIApplication to get keyWindow

    extension UIApplication {
       static var key: UIWindow? {
         if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
         } else {
            return UIApplication.shared.keyWindow
         }
      }
    }

Usage:

let rootViewController = UINavigationController(rootViewController: destVC)
UIApplication.key?.rootViewController = rootViewController

Previous Answer

let rootViewController = UINavigationController(rootViewController: destVC)
    UIApplication.shared.keyWindow?.rootViewController = rootViewController 

Upvotes: 4

Daniel T.
Daniel T.

Reputation: 33967

You have removed your navigation controller from the view hierarchy. Let's look at the code you posted:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let destVC = self.storyboard?.instantiateViewController(withIdentifier: "home_view")
let rootViewController = appDelegate.window?.rootViewController as! UINavigationController
// at this point your window's root view controller is a navigation controller.
appDelegate.window?.rootViewController = destVC
// In the above, you replaced the navigation controller with your destVC.

It's like you took your sneaker off to put on your dress shoe, then you are asking why your sneaker isn't on your foot anymore.


The solution is to put a navigation controller in between your tab bar controller and the view controller that needs a navigation controller.

Upvotes: 3

Related Questions