markhorrocks
markhorrocks

Reputation: 1548

Swift 3 trying to create and use a UINavigationController programmatically

I'm working on an existing application which uses the storyboard but I want to continue development without using the storyboard at all, or nib files.

The existing left menu is a UITableView which is not the root controller and does not have a navigation controller associated with it. I have created a UINavigationController in the app delegate and want to use this navigation controller to push a new controller. I am able to present a view controller but I want to use push in order to conform with the current UIX.

In the following code nothing happens because navigationController? returns nil.

Here is my new code in the app delegate.

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

var navController: UINavigationController?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    navController = UINavigationController()

    self.window = UIWindow(frame: UIScreen.main.bounds)

    self.window!.rootViewController = navController

    self.window!.backgroundColor = .red

    self.window!.makeKeyAndVisible()

    let menuViewController = SideMenuViewController()

    menuViewController.navController = navController

Then in my side menu controller:

import UIKit

class SideMenuViewController: UIViewController {

var navController: UINavigationController?

.......

   let myViewController = myViewController()

   self.navigationController?.pushViewController(myViewController, animated: true )

Upvotes: 0

Views: 569

Answers (1)

thm
thm

Reputation: 1227

From the UIViewController documentation:

var navigation​Controller:​ UINavigation​Controller?
The nearest ancestor in the view controller hierarchy that is a navigation controller.

Which means when you call self.navigationController in a view controller you get the (nearest) navigation controller that self is embedded in. Apparently your menu controller is not embedded in the navigation controller hierarchy. Using your app delegate's navController member is one way to make this work. Then you can say in your menu view controller:

func menuItemFooSelected()
{
    let navController = (UIApplication.shared.delegate as! AppDelegate).navController
    let myViewController = myViewController()
    navController?.pushViewController(myViewController, animated: true)
}

Alternatively (and probably preferably), when you set up your initial structure in your app delegate, inject the navigation controller into the side menu controller:

class MenuViewController: UIViewController
{
    var navController: UINavigationController?
    ...

    func menuItemFooSelected()
    {
        let myViewController = myViewController()
        self.navController?.pushViewController(myViewController, animated: true)
    }
}

In application(_:didFinishLaunchingWithOptions:)

...
let menuViewController = MenuViewController(...)
menuViewController.navController = navController

Upvotes: 1

Related Questions