I finally figured this out. The key missing component, which I didn't mention in the original post, is that the view controller that manages landscape is actually implemented as a modal view. (See the View Controller User Guide for code on how to do this) In concept, I have a Portrait view controller. (which is the primary controller) In the Portrait view controller's viewDidLoad I apply for a Notifier that is triggered off of a change in the orientation like so:
- (void)viewDidLoad {
[super viewDidLoad];
// SECTION to setup automatic alternate landscape view on rotation
// Uses a delegate to bring the landscape view controller up as a modal view controller
isShowingLandscapeView = NO;
// Create Landscape Controller programmatically
self.landscapeViewController = [[LandscapeViewController alloc] initWithNibName:@"LandscapeViewController" bundle:[NSBundle mainBundle]];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
// END SECTION landscape modal view controller
Then, when orientation changes this method is called:
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
// Load Landscape view
landscapeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:self.landscapeViewController animated:YES];
isShowingLandscapeView = YES;
}
At the same time I was removing the status bar from the Landscape view controller's viewWillAppear method:
- (void)viewWillAppear:(BOOL)animated
{
// remove status bar from top of screen
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:animated];
self.myWebView.delegate = self; // setup the delegate as the web view is shown
}
and this is where the problem is introduced. The Portrait view controller captures the screen dimensions, before transitioning to landscape as a Modal View. Then, viewWillAppear, in the Landscape view controller, removes the status bar.
So, the solution is to move the
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:animated];
statement to the orientationChanged method in the Portrait view controller, BEFORE transitioning to the Landscape Modal View.
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
// remove status bar from top of screen
// NOTE: this must be declared BEFORE presenting the Modal View!!!! If it's not, the landscape view will
// contain an ugly white bar in place of the missing status bar at the top of the view.
[[UIApplication sharedApplication] setStatusBarHidden:YES];
// Load Landscape view
landscapeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:self.landscapeViewController animated:YES];
isShowingLandscapeView = YES;
}
Note, that as tc helpfully mentioned above, if you want the status bar to appear when orienting back to Portrait, then you need
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:animated];
in the viewWillDisappear method in the Landscape view controller.