1

I've got an iPhone app with a UIViewController as the first controller. In it, I've got the standard methods that force it to be landscape (see below).

I've also got a second view that I show as a modal in the viewWillAppear -- it's meant as a splash screen while I pull down some content from the 'net.

The problem happens when I physically rotate my device into landscape mode and start the app. The modal shows (in portrait), but when it gets dismissed a few seconds later, the main view is displayed in landscape.

On the other hand, if I comment out the code for the modal and launch the app in landscape, the main view shows up in portrait as it should.

Any suggestions on how I can keep the main view in portrait mode when the app is launched from landscape?

- (void)viewWillAppear:(BOOL)animated {
   // Show the loading splash screen until the webview has completed
   [self performSegueWithIdentifier:@"sgImageModal" sender:self];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
   if ([segue.identifier isEqualToString:@"sgImageModal"]) {     
       splashScreen.modalPresentationStyle = UIModalPresentationFullScreen;        
   }
}

- (BOOL)shouldAutorotate {
    return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [self viewWillAppear:animated];
}

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

Update 1

As per suggestions, I've moved the logic to display the modal into viewDidAppear and viewDidLoad. I also changed shouldAutorotate to return YES. Neither had the desired impact.

bugfixr
  • 7,997
  • 18
  • 91
  • 144

1 Answers1

0

You can't present a modal view controller until the current view controller has finished it's loading, or finished it's transition. 90% of the time, this means you have to present a modal view controller in viewDidAppear: as opposed to viewWillAppear:. The problem is, that when code is executed in viewWillAppear:, the view may not be finished it's setup (including figuring out which orientation to present itself in).

Here is a handy answer by Jacob Knobel which explains exactly when each view lifecycle method is called.

Therefore, if you want the splash screen to appear right away, make it present without animation, presenting it from viewDidAppear:. Upon launching your application your modal should appear right away.

Edit - Have you tried returning YES from shouldAutorotate? You've specified your supported interface orientations, and told it that it should automatically rotate if the orientation is portrait, however you've told it that it shouldn't automatically rotate?

Community
  • 1
  • 1
John Rogers
  • 2,192
  • 19
  • 29
  • This is partly true. You can actually have a view controller present another from `viewDidLoad`. In that case, the `viewWill|DidAppear` methods of the first are not called until the second is dismissed. – rmaddy Apr 29 '15 at 01:16
  • You can, but this really isn't advised and can yield unpredictable results. At runtime, the `viewDidLoad` method may be called again, for example if the runtime needs to release/reload a controller in the case of a memory warning. In this case, your view controller would be presented again, which isn't ideal! – John Rogers Apr 29 '15 at 01:18
  • A quick change to my code moving this to viewDidAppear still causes the main view to show up in landscape. – bugfixr Apr 29 '15 at 01:18
  • @JohnRogers `viewDidUnload` hasn't been used since iOS 5. – rmaddy Apr 29 '15 at 01:20
  • True. You get the idea. Don't use `viewDidLoad` to present view controllers, was my intended takeaway from the comment. – John Rogers Apr 29 '15 at 01:20
  • @JohnRogers Thanks for the suggestion - I guess I didn't understand what shouldAutorotate did. In any case, changing to YES didn't help in this situation. – bugfixr Apr 29 '15 at 01:38