The view controller lifecycle is described in View Controller Programming Guide for iOS.
In short, when -view
is called the first time, -viewDidLoad
is called. Even if the very first thing a view controller does to a view is set the frame, it still needs to access the view.
UIViewController *controller = [MyViewController myViewController];
// -viewDidLoad has not been called (if +myViewController doesn't call -view.)
UIView *view = [controller view];
// -viewDidLoad has been called.
view.frame = [UIApplication sharedApplication].delegate.window.bounds;
Even if you use controller.view.frame
the same logical sequence happens. -viewDidLoad
will always be a called with a freshly deserialized view that has not been embedded into the view hierarchy.
Update
It case it wasn't clear earlier, I was pointing out why the bounds of view are not set correctly in -viewDidLoad
. It is only after -viewDidLoad
does the view controller's view get added to the view hierarchy. This is when the final frame of the view is set.
If you must have the frame be the right dimensions, you can use IB to set the dimensions that you know you'll need or (if you don't use IB) set the frame in -loadView
. This approach is flawed because it statically sets the size of the frame to a value that may be changed after -viewDidLoad
is called (things like the in-call status bar).
Update 2
You need to split the adding subviews from positioning and sizing subviews.
If you are loading from a Storyboard or a Nib, then you are correct, additional views needed should be added in -viewDidLoad
. If you're loading programmatically, then all subviews are added in -loadView
.
The second task is positioning and sizing subviews. The preferred method is to use UIView.autoresizingMask, but for more precise layout, KVO view.bounds and adjust your custom subviews when view controller's view changes its size.