ViewController Wrong bounds before ViewDidAppear (Xcode 7 beta)

Hi.


Only when running an in debug mode on Xcode 7.


The app is only intended for mobile phones (not tablets) and is set to only display in portrait mode.


Any View Controller's bounds seem to only be correct once viewDidAppear has been called. This happens when I use Xcode 7 to run an app in debug mode on a device running iOS 7, 8 or 9.


When using identical code on Xcode 6 and running an app on devices using iOS 7, 8 or 9, the View Controller's bounds seem to be correct at the viewWillAppear point.


This issue is less than ideal as it means that an accurate representation of the View Controller's contents cannot be displayed while a View Controller is in the middle of a 'push' animation when calling [self.navigationController pushViewController: animated:]


Any advice/telling me this is an Xcode 7 bug (😝) would be much appreciated!


Do note the following:


I've had to set ENABLE_BITCODE to NO (only while I try to make the app somewhat iOS 9 compatible.) because of a Google Analytics library issue. Don't know if this could be causing the issue?

Replies

Shameful bump

Are the bounds correct in viewDidLayoutSubviews?

I'm still getting this in iOS 9 beta 5.


The docs for viewWillAppear say:
"For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented."


Which certainly sounds like the view should have the correct bounds at this point, but it's not correct until some time between viewWillAppear and viewDidAppear. Possibly worth filing a bug report with Apple?

fwiw, I'm seeing this issue as well: specifically, adding view controllers to a navigation controller doesn't seem to size the view appropriately. My code has worked flawlessly since iOS 7. Hoping the GM addresses this… :-(

I'm quite surprised this bug has made it into the final release of iOS 9. There doesn't seem to be any official mention from Apple that they have changed how the view lifecycle works, yet this is a major breaking change!


It seems to me the whole point of `viewWillAppear:` is to do things in your view controller after it has been laid out but before it has been rendered on screen. It feels very weird to not have the correct dimensions for the view by this point, especially when this is how it always used to work.


The documentation states "Use a method like

viewWillAppear:
to prepare your views to appear onscreen.
" Well it's kind of hard to do that if it doesn't even know what size it is going to be!


I've had to move much of my code from `viewWillAppear:` into `viewDidLayoutSubviews:`, however it feels ugly to do this logic here. Is there no longer any method called after the view's frame has been set but before it has been drawn?


Where does Apple recommend we put view adjustment logic now? `viewDidAppear:` is clearly too late.

It's common for assumptions about undocumented behaviour to cause problems on an SDK update. In this case it's your assumption that layout has been performed by the time viewWillAppear is called. I don't think Apple has ever guaranteed that; the proper place to do stuff that depends on layout having been performed is in viewDidLayoutSubviews. viewWillTransitionToSize, traitCollectionDidChange et al are also useful if you are making major changes (add/remove subviews) based on your view's size. But I don't think those guarantee that layout has been done either - they're more for ensuring that your view hierarchy and constraints are set up correctly in preparation for a layout pass. viewDidLayoutSubviews is the One True Place for doing things based on the geometry of existing views I think.

This goes deeper than just assumptions about whether subviews have been laid out, though. For example, this scenario is currently reproing in my app:


1. Open VC A in portrait

2. Push VC B onto navigationController

3. Rotate to landscape

4. Pop back to VC A via navigationController

5. VC A receives viewWillAppear, with view size of portrait (!!)


There's no upside to viewWillAppear reporting portrait dimensions when the view is about to appear in landscape.


At this point I can't trust the view dimensions reported in viewWillAppear--I have to work around it.