Obscure iPhone: viewDidLoad and loadNibNamed

Quick tip.

Sometimes, instead of traditional nib loading, you may want to use the following method:

[[NSBundle mainBundle] loadNibNamed:@"MyViewController" owner:self options:options];

For instance, if you want to provide a runtime replacement for proxy object in your nib (see UINibExternalObjects).

If you do this and you also need to perform setup after the nib loads, you’ll come across an unexpected behavior.

viewDidLoad will not be called (Nor does awakeFromNib).

I wouldn’t classify it as a “bug”, I can see the rationale, but it is dubious and I have (so far) been unable to find any documentation on this behavior.

So if you do need to do some setup, place it in viewWillAppear (You are using a UINavigationController or UITabBarController, aren’t you?).

2 Comments

  1. Posted November 18, 2009 at 10:51 am | Permalink

    I load nibs like that all the time, and viewDidLoad will get called… whenever the view is loaded. What’s happening is that loadNibNamed just creates the view controller, but the main view won’t be loaded until you access it.

    So for example, calling loadNibNamed followed by adding its view to some hierarchy will cause the view to be loaded and viewDidLoad to be called.

    But yes, you have to watch out for that because otherwise it’s possible to do operations on the view controller before the viewDidLoad function is called and can lead to unexpected results (I’ve had my share of bugs because of that early on).

  2. Corey
    Posted November 18, 2009 at 12:39 pm | Permalink

    Interesting.

    As far as I know, loadNibNamed does not create the view controller, the view controller is already instantiated. The view controller being the top level object of the nib is simply a proxy (file’s owner).
    It simply unarchives the nib, places those objects in memory, and connects the outlets.

    You can of course instantiate a second view controller within a nib, if it is not the top level object. I wonder if this is the way you are accomplishing this?

    In that case, I would fully expect viewDidLoad to be called.

    In my case, I am loading the nib within the init method of top level view controller. This may in fact be the cause of the problem.