This question is about iOS device rotation and multiple controlled views in a UINavigationController. Some views should be constrained to portrait orientation, and some should autorotate freely. If you try and create the simplest setup with three views, you'll notice that the autorotation behavior has a few very nasty quirks. The scenario is, however, very simple, so I think I'm either not doing the autorotation implementation correctly, or I'm forgetting something.
I have a very basic demo app that shows the weirdness, and I made a video showing it in action.
The setup is very basic: Three view controllers called FirstViewController
, SecondViewController
and ThirdViewController
all extend an AbstractViewController
that shows a label with the class' name and that return YES for shouldAutorotateToInterfaceOrientation:
when the device is in portrait orientation. The SecondViewController overrides the this method to allow for all rotations. All three concrete classes add a few colored squares to be able to navigate between the views by pushing and popping the controllers onto/off the UINavigationController
. So far a very simple scenario, I would say.
If you hold the device in portrait or landscape orientation, this is the result I would not only like to achieve, but would also expect. In the first image you see that all views are 'upright', and in the second you see that only the second view controller counter-rotates the device's orientation. To be clear, it should be possible to navigate from the second view in landscape mode to the third, but because that third only supports portrait orientation, it should only be shown in portrait orientation. The easiest way to see if the results are alright, is by looking at the position of the carrier bar.
But this question is here because the actual result is completely different. Depending on what view you're at when you rotate the device, and depending on what view you navigate to next, the views will not rotate (to be specific, the didOrientFromInterfaceOrientation:
method is never called). If you're in landscape on the second and navigate to the third, it will have the same orientation as the second (=bad). If you navigate from the second back to the first however, the screen will rotate into a 'forced' portrait mode, and the carrier bar will be at the physical top of the device, regardless of how you're holding it. The video shows this in more detail.
My question is twofold:
Cheers, EP.
EDIT: As a last resort before putting a bounty on it, I completely rewrote this question to be shorter, clearer and hopefully more inviting to give an answer.
Set the supportedInterfaceOrientations property of specific UIViewControllers like this: class MyViewController: UIViewController { var orientations = UIInterfaceOrientationMask. portrait //or what orientation you want override var supportedInterfaceOrientations : UIInterfaceOrientationMask { get { return self.
Open project in Xcode ( ios/Runner. xcworkspace ), choose Runner in the project navigator, select Target Runner and on Tab General in section Deployment Info we can setup Device Orientation : Setup a device orientation in Xcode.
From the main screen, slide the top of the screen down. Then, slide the top of the screen down again. Tap the "Portrait" icon to enable landscape mode, or tap the "Auto rotate" icon to disable it. Note: When "Auto rotate" is enabled, the interface will rotate when you hold the phone horizontally.
The short answer is that you're using UINavigationController, and that won't work like you want it to. From Apple's docs:
Why won't my UIViewController rotate with the device?
All child view controllers in your UITabBarController or UINavigationController do not agree on a common orientation set.
To make sure that all your child view controllers rotate correctly, you must implement shouldAutorotateToInterfaceOrientation for each view controller representing each tab or navigation level. Each must agree on the same orientation for that rotate to occur. That is, they all should return YES for the same orientation positions.
You can read more about view rotation issues here.
You'll have to roll your own view/controller stack management for what you want to do.
Make a bolean in App delegate to control which orientation you want for example make a bool to enable Portrait and in your view controller you want to allow Portrait enable it by shared application
in your view controller,where you want to enable or disable what ever orientation you want.
((APPNAMEAppDelegate *)[[UIApplication sharedApplication] delegate]).enablePortrait= NO;
in App Delegate.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { NSLog(@"Interface orientations"); if(!enablePortrait) return UIInterfaceOrientationMaskLandscape; return UIInterfaceOrientationMaskLandscape|UIInterfaceOrientationMaskPortrait; }
These method will be fired each time you rotate the device, Based on these BOOL enable the orientation you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With