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.
source to share
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.
source to share