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.
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).
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.
Even if I request [controller view] immediately after creating the controller, it makes no difference. First I create the controller. Second, I (for now) just assign the controller's view to a variable - just to reference it. Then I change the frame. For any demand-loaded cycles this works - for any triggered in the view didLoad of the mainVC, it does not. If I have misunderstood, and you are referring to my mainVC in your example, then how am I meant to load some other view controllers at launch, and add their views?
Sorry, maybe I wasn't clear-viewDidLoad will always be called before the final bounds or frame is set. Always. There is nothing you can do about it.
Where should I add subviews? In viewWillAppear? Seems like I would be doing a lot of unnecessary reprocessing.
The short answer is split add subviews from positioning and sizing subviews.
@Jeffery Thomas: I have a similar question here, I think your feedback would be useful: stackoverflow.com/questions/17882199/