It's a feature, not a bug

Today I learned something new about UIViewController, I thought it's a bug but it's not.

Here is the situation, I have a ManageBankCardViewController which manage ManageBankCardView and AddBankCardView and swith between the two views based on current user's state.

Build and run, I got a exception:

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

I found people got this exception because they didn't set up their nib file correctly. I checked and rechecked my nib file for ManageBankCardView, but that's not the case. I even re-created the nib file to make sure everything is ok. Still I got this exception and it drived my crazy. Then I was suspicious that something's wrong with Xcode and started digging into project.pbxproj.

Several days later, I found [this] (https://developer.apple.com/documentation/uikit/uiviewcontroller/1621487-nibname):

If you use a nib file to store your view controller's view, it is recommended that you specify that nib file explicitly when initializing your view controller. 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. Specifically, it looks for a nib file with an appropriate name (without the .nib extension) and loads that nib file whenever its view is requested. Specifically, it looks (in order) for a nib file with one of the following names:

If the view controller class name ends with the word ‘Controller’, as in MyViewController, it looks for a nib file whose name matches the class name without the word ‘Controller’, as in MyView.nib.

It looks for a nib file whose name matches the name of the view controller class. For example, if the class name is MyViewController, it looks for a MyViewController.nib file.

It turns out that UIViewController will automatically use nib file with a similar name. FML.

So I have two solutions:

  • Change the name of ManageBankCardView.
  • Override loadView.