As the ShouldAutorotateToInterfaceOrientation
is deprecated in iOS 6 and I used that to force a particular view to portrait only, what is the correct way to do this in iOS 6? This is only for one area of my app, all other views can rotate.
16 Answers
If you want all of our navigation controllers to respect the top view controller you can use a category so you don't have to go through and change a bunch of class names.
@implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
@end
As a few of the comments point to, this is a quick fix to the problem. A better solution is subclass UINavigationController and put these methods there. A subclass also helps for supporting 6 and 7.

- 2,867
- 1
- 17
- 17
-
3I can confirm this works. You may also replace "[self.viewControllers lastObject]" with "self.topViewController" if you like. – Wayne Liu Sep 23 '12 at 09:02
-
@aprato do I need to remove the old shouldAutorotateToInterfaceOrientation references from my code? – jMelnik Sep 26 '12 at 19:35
-
1@jMelnik If your app is only going to be iOS 6.0+, then yes, I would think you should. However, if you're going to support anything less than iOS 6.0, (5.1 and before), you should not change everything over yet as `shouldAutorotate` and `supportedInterfaceOrientations` are only iOS 6.0+. – JRG-Developer Sep 27 '12 at 12:05
-
3If you are using UITabBarController than this UINavigationController category is no help. You should make category on UITabBarController instead... – Borut Tomazin Oct 01 '12 at 08:57
-
46Problem with this solution is that it doesn't work when you pop controller that was in landscape and your new top controller supports only portrait (or vice versa), those callbacks are not called in this case and I am yet to find way how to force new top controller into correct orientation. Any ideas? – Lope Oct 06 '12 at 10:21
-
@Lope have you made sure your nav controller is root to the key window? Which of the new rotation methods have you implemented? – Anthony Oct 07 '12 at 16:27
-
4I subclassed UINavigationController and set it as window.rootController. I implemented all 3 methods, it works great when you change rotation of device, problem is that those methods (and nothing related to rotation) is called when you pop view controller – Lope Oct 07 '12 at 22:43
-
@aparto could u please answer my question, I followed your answer for the current question during implementation. http://stackoverflow.com/questions/13325801/force-then-lock-orientation-of-uiviewcontroller-added-to-a-uinavigationviewcon – Pranav Jaiswal Nov 11 '12 at 08:22
-
@Lope - Same exact issue here. Have you found anything? Supremely lame that Apple forces this design on every app imho. – toblerpwn Dec 01 '12 at 23:21
-
@toblerpwn - sadly, I did not. I was forced to abandon landscape orientation and my apps now work only in portrait – Lope Dec 04 '12 at 15:32
-
I thought doing this myself, but seeing UIViewController defines those methods in categories itself, it should be safer to override them in subclasses. Also it does not cover the case when you push/pop/present a portrait only VC from a landscape one. – Rafael Nobre Jan 21 '13 at 19:37
-
4If I am doing push or pop from landscape view controller then this force UIViewController changes into Landscape. However if I rotate into portrait then it works fine and it will never changed into landscape. The only problem while push or pop from landscape. Please help – Tariq Jan 30 '13 at 16:30
-
@lope see my answer below regarding forcing portrait – Craig Watkinson Feb 24 '13 at 22:39
-
@toblepwn see my answer below regarding forcing portrait – Craig Watkinson Feb 24 '13 at 22:40
-
@BorutTomazin I have tabBarController having navigationControllers on each tab then What will be the solution? Any help will be appreciated. – The iCoder Nov 20 '13 at 07:19
-
@Lope Over three months later and still no fix for this. Anyone? Anyone?? – Nick Mar 02 '14 at 16:33
-
@Lope, It has been a year now. Did you get a proper solution for this? I have the same issue. – Noundla Sandeep Mar 27 '15 at 13:05
-
@noundla I don't think I did, I change the design of the app so that I don't need it and then forgot about the issue. It's just not worth my nerves to work around questionable Apple's design decisions – Lope Mar 27 '15 at 15:36
The best way for iOS6 specifically is noted in "iOS6 By Tutorials" by the Ray Wenderlich team - http://www.raywenderlich.com/ and is better than subclassing UINavigationController
for most cases.
I'm using iOS6 with a storyboard that includes a UINavigationController
set as the initial view controller.
//AppDelegate.m - this method is not available pre-iOS6 unfortunately
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
//MyViewController.m - return whatever orientations you want to support for each UIViewController
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

- 3,976
- 9
- 30
- 39

- 1,018
- 10
- 10
-
1
-
2@Phil, Its works fine for iOS 6. But in some cases, like if you go from landscape to portrait then it doesn't work. Any idea why it happens? – Kirti Nikam Jun 25 '13 at 12:45
-
1
-
1Working on iOS 7 beta 6. Works when going from landscape to portrait in my case. – Martin Berger Sep 03 '13 at 12:39
-
I'm in iOS 6 but this doesn't work. It breaks on the "UIViewController *presentedViewController" line. – Marcel Marino Oct 31 '13 at 16:12
-
I tried so many other solutions, but this is the only one that worked for me. It works great in iOS 6 & iOS 7 and was relatively easy to implement compared with other proposed solutions. – Aaron Feb 17 '14 at 20:13
-
This doesn't work for me. When rotating from portrait to landscape (or vice versa) on a viewController that only supports portrait, it 'locks' all the other viewControllers that support both portrait AND landscape. – Nick Mar 02 '14 at 16:55
-
-
This answer relates to the questions asked in the comments of the OP's post:
To force a view to appear in a given oriention put the following in viewWillAppear:
UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
}
It's a bit of a hack, but this forces the UIViewController
to be presented in portrait even if the previous controller was landscape
UPDATE for iOS7
The methods above are now deprecated, so for iOS 7 use the following:
UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
UIViewController *c = [[UIViewController alloc]init];
[c.view setBackgroundColor:[UIColor redColor]];
[self.navigationController presentViewController:c animated:NO completion:^{
[self.navigationController dismissViewControllerAnimated:YES completion:^{
}];
}];
}
Interestingly, at the time of writing, either the present or dismiss must be animated. If neither are, then you will get a white screen. No idea why this makes it work, but it does! The visual effect is different depending on which is animated.

- 19,381
- 28
- 133
- 216

- 903
- 10
- 20
-
-
@RohanAgarwal it does work as advertised, I'm using it here. But you need to have the accepted answer's code implemented as well, or it won't work. – Dennis Munsie May 18 '13 at 22:48
-
2Has anyone figured out how to make this work with the correct rotation animation at the same time? It's a little jarring to see it switch from portrait to landscape without the animation. It works, just hoping to make it work a little better. – Dennis Munsie May 18 '13 at 22:50
-
@Craig Watkinson It is not working in storyboard. and presentModalViewController and dismissModalViewControllerAnimated is deprecated if iam using presentVirecontroller then it wont work .please help me – Kalpesh Aug 22 '13 at 09:29
-
-
thanks it worked, dont know whats going to happen if apple change some thing in its api, have given around two days but can not solve problem of pushing a view in portrait from landscape in navigation based app. – maddy Apr 18 '14 at 15:18
-
1For ios8 dismissViewControllerAnimated just crashes. I found that calling [NWSAppDelegate sharedInstance].window.rootViewController = nil; [NWSAppDelegate sharedInstance].window.rootViewController = previousRootController works nice. – Alexey Sep 02 '14 at 14:36
-
-
@Craig Watkinson its working fine when i Push VC from landscap. but when i popview from landscap its crashing. Reason : 'preferredInterfaceOrientationForPresentation must return a supported interface orientation!' Please help me out on this. – Hitarth Nov 12 '14 at 12:01
So I ran into the same problem when displaying portrait only modal views. Normally, I'd create a UINavigationController
, set the viewController
as the rootViewController
, then display the UINavigationController
as a modal view. But with iOS 6, the viewController
will now ask the navigationController for its supported interface orientations (which, by default, is now all for iPad and everything but upside down for iPhone).
Solution: I had to subclass UINavigationController
and override the autorotation methods. Kind of lame.
- (BOOL)shouldAutorotate {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

- 3,976
- 9
- 30
- 39

- 3,521
- 1
- 23
- 31
-
1doesn't work on mine. I had this code with global setted to all orientations – phil88530 Sep 24 '12 at 21:00
-
2supportedInterfaceOrientations should return an NSUInteger, not BOOL. See http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrientationChanges.html – tomwhipple Oct 09 '12 at 03:26
-
its worked, for me its the tabbarcontroller, again thanks for the answer – otakuProgrammer Oct 09 '12 at 08:27
-
IOS 5
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
IOS 6
-(BOOL)shouldAutorotate{
return YES;
}
-(NSInteger)supportedInterfaceOrientations{
// UIInterfaceOrientationMaskLandscape;
// 24
//
// UIInterfaceOrientationMaskLandscapeLeft;
// 16
//
// UIInterfaceOrientationMaskLandscapeRight;
// 8
//
// UIInterfaceOrientationMaskPortrait;
// 2
// return UIInterfaceOrientationMaskPortrait;
// or
return 2;
}

- 277
- 1
- 4
-
Excellent! Need to be maximally at the top of this thread. Because it is the most simple way to solve problem – Olex Dec 24 '12 at 16:23
-
@Roshan Jalgaonkar In ios 6 It does not work for me i need only portrait with down home button how can i set this UIOrientation.... – Karthik Apr 29 '13 at 12:06
-
@Karthik you have to enable supported rotations in your App's target for this to work. – Alejandro Iván Jul 10 '13 at 22:31
I disagree from @aprato answer, because the UIViewController rotation methods are declared in categories themselves, thus resulting in undefined behavior if you override then in another category. Its safer to override them in a UINavigationController (or UITabBarController) subclass
Also, this does not cover the scenario where you push / present / pop from a Landscape view into a portrait only VC or vice-versa. To solve this tough issue (never addressed by Apple), you should:
In iOS <= 4 and iOS >= 6:
UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];
In iOS 5:
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];
These will REALLY force UIKit to re-evaluate all your shouldAutorotate , supportedInterfaceOrientations, etc.

- 5,062
- 40
- 40
-
2The first of these crashes for me regardless of iOS version. Says dismiss should not be called before present has finished. – arsenius Mar 27 '13 at 07:28
-
@arsenius Can you post a snippet of how you're using it ? As long as it isn't animated it shouldn't have the issue you mention – Rafael Nobre Mar 27 '13 at 17:47
-
I also put the second snippet into viewDidAppear and it does nothing to help my situation on iOS 6. Question is here: http://stackoverflow.com/questions/15654339/support-rotation-in-only-one-tab-on-both-ios-5-and-6 – arsenius Mar 28 '13 at 05:53
-
Sorry, one last comment here. Moving the iOS 5 code to viewDidAppear creates some sort of infinite loop with this output: -[UIApplication beginIgnoringInteractionEvents] overflow. Ignoring. – arsenius Mar 28 '13 at 06:03
I have a very good approach mixing https://stackoverflow.com/a/13982508/2516436 and https://stackoverflow.com/a/17578272/2516436
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
and return whatever orientations you want to support for each UIViewController
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

- 1
- 1

- 320
- 1
- 6
Not to be dull here, but would you be so kind to share your subclass? Thank you.
edit: well, I finally did it, the subclass was dead simple to do. I just had to declare the navigationController
in the AppDelegate
as UINavigationControllerSubclass
instead of the default UINavigationController
, then modified your subclass with:
- (BOOL)shouldAutorotate {
return _shouldRotate;
}
so I can set any view I want to rotate or not by calling at viewDidLoad
_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]
Hope this tweak will help others as well, thanks for your tip!
Tip: Make use of
- (NSUInteger)supportedInterfaceOrientations
in your view controllers, so you don't end up by having a portrait desired view in landscape or vice versa.

- 3,976
- 9
- 30
- 39

- 388
- 1
- 4
- 21
I have a relatively complex universal app using UISplitViewController and UISegmentedController, and have a few views that must be presented in Landscape using presentViewController
. Using the methods suggested above, I was able to get iPhone ios 5 & 6 to work acceptably, but for some reason the iPad simply refused to present as Landscape. Finally, I found a simple solution (implemented after hours of reading and trial and error) that works for both devices and ios 5 & 6.
Step 1) On the controller, specify the required orientation (more or less as noted above)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
NSInteger mask = UIInterfaceOrientationMaskLandscape;
return mask;
}
Step 2) Create a simple UINavigationController subclass and implement the following methods
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
Step 3) Present your viewController
vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];
Hope this is helpful to someone.

- 323
- 3
- 14
I did not test it myself, but the documentation states that you can now override those methods: supportedInterfaceOrientations
and preferredInterfaceOrientationForPresentation
.
You can probably achieve what you want y setting only the orientation that you want in those methods.

- 3,526
- 20
- 31
The answers using subclasses or categories to allow VCs within UINavigationController and UITabBarController classes work well. Launching a portrait-only modal from a landscape tab bar controller failed. If you need to do this, then use the trick of displaying and hiding a non-animated modal view, but do it in the viewDidAppear method. It didn't work for me in viewDidLoad or viewWillAppear.
Apart from that, the solutions above work fine.

- 1,022
- 9
- 12
For Monotouch you could do it this way:
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
{
return UIInterfaceOrientationMask.LandscapeRight;
}
public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
{
return UIInterfaceOrientation.LandscapeRight;
}

- 80
- 2
- 10
I see the many answer but not get the particular idea and answer about the orientation but see the link good understand the orientation and remove the forcefully rotation for ios6.
http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/
I think it is help full.

- 1,748
- 1
- 14
- 29

- 308
- 4
- 8
Just go to project.plist then add Supported interface orientation and then add only Portrait (bottom home button) and Portrait (top home button).
You can add or remove there orientation as per your project requirement .
Thanks

- 1,748
- 3
- 13
- 20
-
1its about particular view controller not for whole application. – Muhammad Rizwan Aug 20 '14 at 12:47
1) Check your project settings and info.plist and make sure that only the orientations you want are selected.
2) add the following methods to your topmost view controller(navigation controller/tabbar controller)
- (NSUInteger) supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
3) add the following methods to your app delegate
- (NSUInteger) supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}

- 9
- 4
Put this in the .m file of each ViewController
you don't want to rotate:
- (NSUInteger)supportedInterfaceOrientations
{
//return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
return UIInterfaceOrientationMaskPortrait;
}
See here for more information.

- 4,617
- 7
- 31
- 35

- 1
- 1