3
votes

I have a UINavigationController as my UIWindow's rootViewController and a UIViewController (ControllerA) that supports only Portrait orientation is added to the UINavigationController as its rootViewController.

At some point later, I replace UINavigationController's rootViewController with a new UIViewController (ControllerB). ControllerB supports both Portrait and Landscape. I want my initial screen (ControllerA) to only work in Portrait while the rest of the app can supports both Portrait and Landscape.

[self.navigationController setViewControllers:@[viewControllerB] animated:NO];

| UINavigationController launches:
| ----ControllerA (rootViewController): Portrait only
| ----ControllerB (rootViewController): Portrait and Landscape supported

If I start my app in Landscape which is not handled by ControllerA and then move to ControllerB, my content (+status bar) is still in Portrait. If I manually rotate the device at this point, I have the correct content layout.

How can I make ControllerB render itself in the orientation of the device?

Here's what I'm seeing from both ControllerA and ControllerB viewWillAppear method:

navigationController orientation: UIInterfaceOrientationPortrait 
UIViewController interfaceOrientation: UIInterfaceOrientationPortrait 

<!-----------!!two values are different!!------------------>
[[UIDevice currentDevice] orientation]: UIDeviceOrientationLandscapeLeft 
[[UIApplication sharedApplication] statusBarOrientation]: UIInterfaceOrientationPortrait 
Phone is physically held in Landscape at this point in time.
1
From my experience, [[UIApplication sharedApplication] statusBarOrientation]: UIInterfaceOrientationPortrait is definitive and is always right. [UIDevice currentDevice] orientation is not reliable that I know of. - HalR
Why does the statusBar report being in portrait mode when ControllerB is set as the NavBar's root but I'm holding it landscape? - Willam Hill
That is a darned good question! - HalR
The one popular workaround seems to be to transform the view: stackoverflow.com/questions/13002477/… but I'm not sure if a better and less hacked solution for use. - Willam Hill
I've been looking into this very question at length. As far as I can tell, there's no way to determine what the orientation should be and rotate it there. - Kevin

1 Answers

0
votes

Here is the easiest solution (iOS7 only) but it can be expanded to work down to iOS5.

Just write our own UINavigationController (or write a category) and implement supportedInterfaceOrientations.

@implementation MyNavigationController

- (NSUInteger)supportedInterfaceOrientations
{
    return self.topViewController.supportedInterfaceOrientations;
}

@end

When you want to know the interface orientation always use UIViewController.interfaceOrientation. The statusbar orientation might be wrong (in case of multiple windows) and the device orientation is totally wrong since the device can be Face Up (laying flat on a table) and you cannot infer the interface orientation from that.