When to (not) use UIViewController::loadView

It is pretty confusing how one is supposed to use the loadView method. My initial understanding was “do not implement loadView if you have a nib file, do implement it to create your view controller’s view in code.” Fine. But what if you are writing a middle layer UIViewController subclass that programmatically constructs part of the view hierarchy? Where should you do so? The answer is the UIViewController::loadView documentation, so let’s study it line by line (more or less).

- (void)loadView

You should never call this method directly. The view controller calls this method when its view property is requested but is currently nil. This method loads or creates a view and assigns it to the view property.

So if you refer to [self view] early on you may trigger loadView if your view controller’s view property is still nil.

If the view controller has an associated nib file, this method loads the view from the nib file. [...] If the view controller does not have an associated nib file, this method creates a plain UIView object instead.

This is key: loadView IS called even if your v.c. uses a nib file. We can infer that UIViewController’s implementation of loadView NEEDS to be reached since that’s the only place that can possibly do “load the view from the nib file.

If you use Interface Builder to create your views and initialize the view controller, you must not override this method. You can override this method in order to create your views manually. [...] Your custom implementation of this method should not call super.

Ok, this makes sense: if your v.c. uses a nib, do not override loadView. However this has subtle ramifications. If you have a hierarchy of view controllers such asĀ AppVC : MyFrameworkVC : UIViewController, it follows that MyFrameworkVC must ALSO NOT override loadView. If it did, its custom implementation is required not to call [super loadView] which would imply that the [UIViewController loadView] logic (that parses the nib, see above) will not be invoked. And that would be wrong.

So this means that loadView is just meant to build the view hierarchy from scratch. Nothing else. It is an application-level method and should be extended once in application code only.

Finally,

If you want to perform any additional initialization of your views, do so in the viewDidLoad method.

leaves it open to programmatically create new subviews in viewDidLoad, if needed, whether you’re using nibs or not.

Final corollary

All of this made me realize something perhaps obvious to many: Apple docs are targeted toward application coders, not much framework developers. That’s more likely their target audience. Once you make this realization (totally not obvious to me) the docs make more sense.

Summary

- if you’re writing framework code, never implement loadView. You can’t make the assumption your clients will use nibs or not. Do not choose for them: you’ll end up with clusterfucks like Three20, which does everything wrong (plenty of [super loadView] there). If you have some view initialization code that your subclasses might benefit from, put it in a new method, such as loadBaseView.

- if you’re writing application code and you use nibs, never implement loadView. Stick to viewDidLoad.

- if you’re writing application code and you do NOT use nibs, implement loadView and don’t call [super loadView]. Your loadView code should produce a functional and complete view hierarchy and assign the v.c. view property.

Posted in: iOS

Tags: , ,



addLeave a comment