loadView
vs viewDidLoad
For programatic UI setup
I was talking to Justin Driscoll on Twitter on setting up the view
hierarchy in code, and whether the best place to do that was loadView
or viewDidLoad
(Update: when you inherit directly from
UIViewController
).
Developers who choose to setup their view hierarchy in loadView
do so like this:
Here is one example of this strategy.
Developers who choose to setup their view hierarchy in viewDidLoad
do so like this:
Here is an example of this strategy.
If we setup the view hierarchy in viewDidLoad
and we want a custom
view as the root view, we should also implement a custom loadView
:
Both of these strategies work. So which one is better?
What does Apple recommend?
Apple’s documentation does talk about setting up the view hierarchy in code without using Interface Builder.
View Controller Programming Guide:
If you prefer to create views programmatically, instead of using a storyboard, you do so by overriding your view controller’s
loadView
method. Your implementation of this method should do the following:
Create a root view object. …
Create additional subviews and add them to the root view.
For each view, you should:
- Create and initialize the view.
- Add the view to a parent view using the
addSubview:
method.If you are using auto layout, assign sufficient constraints to each of the views you just created to control the position and size of your views. Otherwise, …
Assign the root view to the
view
property of your view controller.
If you cannot define your views in a storyboard or a nib file, override the
loadView
method to manually instantiate a view hierarchy and assign it to theview
property.…
You can override [the
loadView
] method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the view property.…
If you want to perform any additional initialization of your views, do so in the
viewDidLoad
method.
So, as per Apple’s documentation, the recommended place to setup the
view hierarchy is loadView
.
Apple suggests we do “any additional initialization” of our views in
viewDidLoad
. I interpret that as: If you’d like to setup additional
views on top of what’s in your storyboard or xib, do it in
viewDidLoad
.
While it’s not entirely clear what “additional initialization” is meant
to be done in viewDidLoad
, it’s quite clear that loadView
is the
recommended override point for setting up the view hierarchy in code.
Practically speaking
I see a lot of code that sets up the view hierarchy in viewDidLoad
without setting up the views in Interface Builder. Though that doesn’t
strictly follow what Apple recommends we do, that’s perfectly safe,
because of the way in which a view controller loads its view.
When the view
property of a UIViewController
is accessed, a
simplified pseudocode for returning a view looks something like this
1:
If there’s already a view set, return that view
Call
loadView
The default implementation of
loadView
inUIViewController
does something like this 2:
- If there’s an associated storyboard / xib,
- Load the view hierarchy from the storyboard / xib
- Assign the root view to the
view
property- If there’s no associated storyboard / xib
- Create a
UIView
instance with a defaultframe
andautoResizingMask
- Assign that view to the
view
propertyFor any layout guides created from a storyboard / xib, setup Auto Layout constraints between the layout guides and the view of the view controller
Call
viewDidLoad
So, when you’re not using a storyboard or xib, viewDidLoad
gets called
almost immediately after loadView
. In practice, it makes no difference
whether you setup the view hierarchy in loadView
or viewDidLoad
.
I personally prefer doing it in loadView
, which is consistent with
Apple’s documentation, but I have seen a lot of code that does it in
viewDidLoad
.
To conclude, we can set up the view hierarchy in either loadView
or
viewDidLoad
, as long as we’re aware of when which method gets called.
The most important thing to remember is that if you override loadView
,
you should set the view
property, while if you override viewDidLoad
,
you should only read the view
property, which should have been already
set.
(Update: Note that this post applies only when your view is a direct
subclass of UIViewController
. When you’re inheriting from a subclass
of UIViewController
, like say UITableViewController
, you should
build up your view hierarchy in viewDidLoad
.)
If you liked this post, you might also like: Doing it all in code