viewDidLoad self.traitCollection undefined

I'm seeing times when self.traitCollection is undefined in viewDidLoad:

If I do the following simple presentation - the traits are NOT set (in viewDidLoad:)


TableViewController* vc = [[TableViewController alloc] initWithStyle:UITableViewStylePlain]; 
vc.modalPresentationStyle = UIModalPresentationFullScreen; 
[self presentViewController:vc animated:YES completion:nil];


However, if I use UIModalPresentationCurrentContext the traits ARE set (in viewDidLoad:)


Stranger still - if I insert a navigation controller as follows, the traits ARE set (in viewDidLoad: even with FullScreen presentation mode)


TableViewController* vc = [[TableViewController alloc] initWithStyle:UITableViewStylePlain]; 
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:vc]; 
nav.modalPresentationStyle = UIModalPresentationFullScreen; 
[self presentViewController:nav animated:YES completion:nil];


Obviously my 'solution' is to use CurrentContext - but I'm not clear whether this is a bug or a gap in my understanding. Any pointers would be most welcome.


I'm using iOS 8.3


Thanks

Generally speaking, you can't do any sort of layout of any kind in viewDidLoad. The view has not yet been added the hierarchy so you have no idea whether it's going to be in a tiny portion of an iPhone screen as a child view controller, or full screen on some monstrous iPad from the future. It makes sense that the trait collection should not be known at that point.


I would think the layout-related methods such as viewWillLayoutSubviews, viewWillTransitionToSize, willTransitionToTraitCollection etc. might be more appropriate places to respond to different layouts.


Disclaimer: I haven't tackled this yet in my own apps; they are still using pre-size classes storyboards.

Thanks for taking the time to reply.


I need to decide in viewDidLoad: what type of screen elements to create. If I'm compact, I might create a smaller toolbar for example.

As I understand it, UIViewControllers inherit traitCollections - so it shouldn't matter that the view has not been added to the hierarchy yet. Not sure it explains the discrepency between FullScreen and CurrentContext either.


Thanks.

You might be right there that there are more subleties in the view controller hierarchy as opposed to the view hierarchy. I haven't done a whole lot that required me to learn about that part yet. (If you present a VC using "FullScreen" while you are a tiny little child view controller, would you expect it to inherit the tiny little child VC's trait collection?) Not sure what the extra navigation controller is doing when it presents your VC - maybe it is using CurrentContext internally.


But in any case, the trait collection can change later on at runtime, so you have to respond in those other methods anyway, right?

Yes, I respond to willTransitionToTraitCollection: and adapt toolbars etc. But that function is not called when the VC is created/displayed - only when it changes during the lifetime of the VC.


It's all a bit odd - and I can't find any clear documentation - other than that one WWDC vid from 2014 :-(

Hopefully Rincewind will come in with an explanation then.

viewDidLoad self.traitCollection undefined
 
 
Q