View Controller Triggers View UIApplicationDidChangeStatusBarOrientationNotification

I have a universal app that supports iPad and iPhone, and on iPhone it does UIInterfaceOrientationPortraitUpsideDown

.

When I launch the app on the iPhone, rotate the device on UIInterfaceOrientationPortraitUpsideDown

and then present the view controller like this:

UIViewController* vc = [[UIViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController* navigationController = [[UINavigationController alloc]
                                              initWithRootViewController:vc];
navigationController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:navigationController animated:YES completion:nil];

      

This is very unexpected UIApplicationDidChangeStatusBarOrientationNotification

.

OK, maybe this is because the modal view controller does not support vertical portrait orientation. Let's make your own subclass UIViewController

that overrides supportedInterfaceOrientations

:

- (NSUInteger) supportedInterfaceOrientations
{
  return UIInterfaceOrientationMaskAll;
}

      

But no difference representing the custom VC still triggers the notification. I also noticed that notifications are not triggered on iPad, only on iPhone. Finally, the behavior is the same in iOS 8 and iOS 7 (specifically, I'm testing iOS 8.1 and iOS 7.1, but I doubt it matters).

Question: Is it normal for this notification to be sent when a modal VC is presented? Why does this only happen for UIInterfaceOrientationPortraitUpsideDown

, but not for a normal portrait or either of the two landscape orientations? And why does this only happen on the iPhone and not on the iPad?

Note. I can provide a more complete, minimal runtime example upon request.

+3


source to share


1 answer


The problem was that the modally presented view controller did not support UIInterfaceOrientationPortraitUpsideDown

. My idea to add an override supportedInterfaceOrientations

was correct, but my mistake was that I added an override to a custom subclass UIViewController

, but this is not a presented view controller!

The presented view controller, as my code snippet shows, is an instance UINavigationController

. So the correct solution to my problem is to create a subclass UINavigationController

and add supportedInterfaceOrientations

to that subclass.


Another correct, but in my case more elegant solution than subclassing, is to use a protocol UINavigationControllerDelegate

.

Step 1: Change the code snippet from my question:



UIViewController* vc = [[UIViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController* navigationController = [[UINavigationController alloc]
                                              initWithRootViewController:vc];
navigationController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
// --- THE NEXT LINE IS NEW ---
navigationController.delegate = self;
[self presentViewController:navigationController animated:YES completion:nil];

      

Step 2. Make sure the class containing the presentation code (= the above code snippet) is using the protocol UINavigationControllerDelegate

.

Step 3 (yes, there is step 3): Add this protocol method to your new delegate class:

- (NSUInteger) navigationControllerSupportedInterfaceOrientations:(UINavigationController*)navigationController
{
  return UIInterfaceOrientationMaskAll;
}

      

If you have a lot of places where you present view controllers, you probably want to have some kind of generic object that accepts UINavigationControllerDelegate

, but that part of your application's design.

+1


source







All Articles