Search code examples
swiftuiviewcontrolleruinavigationcontroller

UINavigationController(rootViewController: MyViewController()) triggers viewdidLoad and returns nil navigationController


I am trying to understand the logic behind initialising a UINavigationController using the initialiser:

UINavigationController(rootViewController: MyViewController())

The app I am modifying used this initialiser and inside MyViewController custom initialiser I had:

class MyViewController:UIViewController{

    init(){
        super.init(nibName: "MyViewController", bundle: nil)
    }

}

Inside the MyViewController lifecycle methods, the viewDidLoad used to have not nil for the navigationController value.

The only change I have done is inside the custom initialiser. Now:

init(){
    super.init(nibName: nil, bundle: nil)

    /*EDIT*/
    let dummyMe = UIView()
    view.addSubview(dummyMe)

}

In other words, I don't want to use a xib file. That change got me into a crash and, after some debugging, I realised that the navigationController value was nil inside the viewDidLoad method but not in my viewWillAppear method.

How is that possible? Should the UINavigationController initialiser call viewDidLoad? Why is navigationController value nil now?

Thank you


Solution

  • you should check your code. Example works as expected, you can paste it to playground:

    import UIKit
    import PlaygroundSupport
    
    class MyViewController:UIViewController{
        override func viewDidLoad() {
            super.viewDidLoad()
            print(#function)
            print(navigationController)
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            print(#function)
            print(navigationController)
        }
    }
    
    let controller = UINavigationController(rootViewController: MyViewController())
    

    this code will not trigger life cycle methods. Add PlaygroundPage.current.liveView = controller.view to trigger and see:

    viewDidLoad()
    Optional(<UINavigationController: 0x7ffb18001200>)
    viewWillAppear
    Optional(<UINavigationController: 0x7ffb18001200>)
    

    UPD:

    to add custom views override loadView:

    override func loadView() {
        super.loadView()
        let subviewFrame = view.bounds
        let dummyMe = UIView(frame: subviewFrame)
        dummyMe.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        dummyMe.backgroundColor = .yellow
        view.addSubview(dummyMe)
    }
    
    

    or even:

    override func loadView() {   
        let dummyMe = UIView()
        dummyMe.backgroundColor = .yellow
        view = dummyMe
    }