iosuitableviewuinavigationcontrolleruinavigationbarrootview

Navigation Bar Disappears Change Root ViewController and then reassign


I've made the launch screen the root view while my app makes a request to firebase and then reassign the root view once the request has been completed. Unfortunately when I do this my navigation bar disappears or is covered up by the new root view. When I run the simulator I can see the navigation bar briefly and then it get covered up by my TableViewController. How do I keep this from happening?

Here is my code from the AppDelegate where I make all of this happen:

    var window: UIWindow?
let searchManager = SearchManager()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    makeRootViewLaunchScreen()
    FirebaseApp.configure()
    searchManager.getMosaicTitles { results in
        self.searchManager.listOfMosaics = results
        self.stopDisplayingLaunchScreen()
    }
    // Adds border to bottom of the nav bar
    UINavigationBar.appearance().shadowImage = UIImage.imageWithColor(color: UIColor(red:0.00, green:0.87, blue:0.39, alpha:1.0))
    // Override point for customization after application launch.
    return true
}

func makeRootViewLaunchScreen() {
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
    let viewController = mainStoryboard.instantiateViewController(withIdentifier: "launchScreen")
    UIApplication.shared.keyWindow?.rootViewController = viewController
}

func stopDisplayingLaunchScreen() {
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = mainStoryboard.instantiateViewController(withIdentifier: "centralViewController") as? SearchResultsTableViewController
    viewController?.searchManager = searchManager
    UIApplication.shared.keyWindow?.rootViewController = viewController
    UIApplication.shared.keyWindow?.rootViewController?.navigationController?.isNavigationBarHidden = false
}

As you can see I tried to use UIApplication.shared.keyWindow?.rootViewController?.navigationController?.isNavigationBarHidden = false to force the navigation bar to appear but it doesn't. My app still looks like this: what it looks like with missing navigation bar


Solution

  • You are setting a UIViewController as your Root controller. What you want to do is set a UINavigationController as your Root controller.

    Either create a new navigation controller in your storyboard and load that one instead of loading "centralViewController", or modify your function like this:

    func stopDisplayingLaunchScreen() {
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
        if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "centralViewController") as? SearchResultsTableViewController {
    
            viewController.searchManager = searchManager
    
            // create a new UINavigationController
            let newNavVC = UINavigationController()
    
            // set the "root" VC of the NavVC to your SearchResultsTableViewController
            newNavVC.setViewControllers([viewController], animated: false)
    
            // use the new NavVC as the new rootViewController
            UIApplication.shared.keyWindow?.rootViewController = newNavVC
            UIApplication.shared.keyWindow?.rootViewController?.navigationController?.isNavigationBarHidden = false
    
        }
    }
    

    Note: not tested, but this should get you on your way.

    Edit: Another approach...

    Instead of swapping the root controller of the key window, create a ViewController that indicates you are initializing / retrieving your data. That VC can be the "root" of a Navigation Controller.

    Put your searchManager.getMosaicTitles function in that VC. When it has finished, replace the current "launch" controller in your Nav Controller with your TableVC. It will look something like this:

    // note: searchManager will have to be a reference back to AppDelegate.searchManager
    searchManager.getMosaicTitles { results in
        self.searchManager.listOfMosaics = results
    
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
        if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "centralViewController") as? SearchResultsTableViewController {
    
            viewController.searchManager = searchManager
    
            // replace the current Nav VC stack with the new SearchResultsTableViewController
            self.navigationController.setViewControllers([viewController], animated: false)
    
        }
    }