0
votes

I wanted to create UIViewController programmatically without nib, e.g.:

import UIKit

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // code...
    }

    // code...
}

and used it like this:

let vc = MyViewController()
self.present(vc, animated: true, completion: nil)

However, the app crashed:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "MyViewController" nib but the view outlet was not set.'


This is weird because I don't associate any nib files with this view controller.

Cleaning builds, deleting derived data, deleting the app, restarting simulator, Xcode and my Mac didn't work. Adding init() and call super.init(nibName: nil, bundle: nil) also doesn't help.

What's wrong with my code?

1

1 Answers

1
votes

Turns out that I accidentally have a nib file named MyView.xib that is totally unrelated to MyViewController, but the system tries to load that!

When we call MyViewController() (which calls init(nibName: nil, bundle: nil)), the system tries to be smart by finding nib file with similar names, from the nibName documentation:

... However, if you do not specify a nib name, and do not override the loadView() method in your custom subclass, the view controller searches for a nib file using other means.

According to the doc, it searches for these:

  1. MyView.xib
  2. MyViewController.xib

Which is bingo and crashes the app!


Solution: Always override loadView when you create UIViewController programmatically to prevent that behavior:

class MyViewController: UIViewController {

    // OVERRIDE THIS TO FIX!
    override func loadView() {
        super.loadView()
    }

    ...
}

Want to try? https://github.com/aunnnn/ViewController-Nib-Confusion