iOS6: supportedInterfaceOrientations not working (is invoked but the interface still rotates)

IphoneObjective CIosIos6

Iphone Problem Overview


In my app I have multiple views, some views need to support both portrait and landscape, while other views need to support portrait only. Thus, in the project summary, I have all selected all orientations.

The below code worked to disable landscape mode on a given view controller prior to iOS 6:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

Since shouldAutorotateToInterfaceOrientation was deprecated in iOS6 I've replaced the above with:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMask.Portrait;
}

This method is correctly called when the view appears (I can set a breakpoint to ensure this), but the interface still rotates to landscape mode regardless of the fact that I'm returning the mask for portrait modes only. What am I doing wrong?

It seems that it's currently impossible to build an app that has different orientation requirements per view. It seems to only adhere to the orientations specified in the project summary.

Iphone Solutions


Solution 1 - Iphone

If your are using a UINavigationController as the root window controller, it will be its shouldAutorotate & supportedInterfaceOrientations which would be called.

Idem if you are using a UITabBarController, and so on.

So the thing to do is to subclass your navigation/tabbar controller and override its shouldAutorotate & supportedInterfaceOrientations methods.

Solution 2 - Iphone

try change this code in AppDelegate.m

//   self.window.rootViewController = self.navigationController;

    [window setRootViewController:navigationController];

this is the complete answer

https://stackoverflow.com/questions/12260261/shouldautorotatetointerfaceorientation-not-being-called-in-ios-6

XD

Solution 3 - Iphone

In my case I have UINavigationController and my view controller inside. I had to subclass UINavigationController and, in order to support only Portrait, add this method:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

So in the UINavigationController subclass I need to check which orientation is supported by the current topViewController.

- (NSUInteger)supportedInterfaceOrientations
{
    return [[self topViewController] supportedInterfaceOrientations];
}

Solution 4 - Iphone

One thing I've found is if you have an old application that is still doing

[window addSubView:viewcontroller.view];  //This is bad in so may ways but I see it all the time...

You will need to update that to:

[window setRootViewController:viewcontroller]; //since iOS 4

Once you do this the orientation should begin to work again.

Solution 5 - Iphone

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;
}

Solution 6 - Iphone

As stated by others if you're using a UINavigationController and you want to customize various views you'll want to subclass the UINavigationController and make sure you have these two components:

@implementation CustomNavigationController

// -------------------------------------------------------------------------------
//	supportedInterfaceOrientations:
//  Overridden to return the supportedInterfaceOrientations of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations]; 
}

// -------------------------------------------------------------------------------
//	shouldAutorotate
//  Overridden to return the shouldAutorotate value of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  YES when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

Then in any view that is a portrait only you would include:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

And in any view that is everything but upside down:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

Solution 7 - Iphone

Basically as someone stated above, but in more detail:

  1. Create a new file that is a subclass of UINavigationController

  2. Go to your storyboard and then click on the Navigation Controller, set its class to the one that you just created

  3. In this class(.m file) add the following code so it will remain in portrait mode:

     (BOOL)shouldAutorotate
     {
       return NO;
     } 
    
     (NSUInteger)supportedInterfaceOrientations
     {
      return UIInterfaceOrientationMaskPortrait;
     }
    

This worked for me

Solution 8 - Iphone

This code worked for me:

-(BOOL)shouldAutorotate {
     return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

https://stackoverflow.com/questions/12540152/iphone-ipad-app-orientation/12540379 check out my own answer

Solution 9 - Iphone

The best way I think is to do a Category rather than subclassing UINavigationController or UITabbarController

your UINavigationController+Rotation.h

#import <UIKit/UIKit.h>

@interface UINavigationController (Rotation)

@end

your UINavigationController+Rotation.m

#import "UINavigationController+Rotation.h"

@implementation UINavigationController (Rotation)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}


@end

Try to make all your controller import this category and this work like a charm. You can even make a controller not rotating and pushing another controller that will rotate.

Solution 10 - Iphone

Try add shouldAutorotate method

Solution 11 - Iphone

Firstly in order to make your app work in only mode you should be returning UIInterfaceOrientationMaskLandscape. In case you want to keep only portrait mode, you are doing things correctly.

Just add the UISupportedInterfaceOrientations key in the Info.plist and assign the interface orientation values your app intends to keep.

Also, you should be returning false from shouldAutoRotate in case you want to avoid auto rotation totally. But I would suggest you to return true from here and specify the correct orientations in supportedInterfaceOrientations method.

Solution 12 - Iphone

I have the same situation as you. I know you already accepted an answer, but I thought I'd add another one anyway. This is the way I understand the new version of the rotation system to work. The root view controller is the only view controller to ever be called. The reasoning, I believe, is that with child view controllers it doesn't make sense often to rotate their views since they will just stay within the frame of the root view controller anyway.

So, what happens. First shouldAutorotate is called on the root view controller. If NO is returned then everything stops. If YES is returned then the supportedInterfaceOrientations method is invoked. If the interface orientation is confirmed in this method and the global supported orientations from either the Info.plist or the application delegate, then the view will rotate. Before the rotation the shouldAutomaticallyForwardRotationMethods method is queried. If YES (the default), then all children will receive the will and didRotateTo... methods as well as the parent (and they in turn will forward it to their children).

My solution (until there is a more eloquent one) is to query the last child view controller during the supportedInterfaceOrientations method and return its value. This lets me rotate some areas while keeping others portrait only. I realize it is fragile, but I don't see another way that doesn't involve complicating things with event calls, callbacks, etc.

Solution 13 - Iphone

If you are using UINavigationController, you have to implement shouldAutorotate and supportedInterfaceOrientations in subclass of UINavigationController.

These are able to control by two steps, if shouldAutorotate returns YES then effective supportedInterfaceOrientations. It's a very nice combination.

This example, my mostly views are Portrait except CoverFlowView and PreviewView. The CoverFlowView transfer to PreviewView, PreviewView wants to follow CoverFlowCView's rotation.

@implementation MyNavigationController

-(BOOL)shouldAutorotate
{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"PreviewView")])

return NO;

else

return YES;

}



-(NSUInteger)supportedInterfaceOrientations

{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"CoverFlowView")])

return UIInterfaceOrientationMaskAllButUpsideDown;

else

return UIInterfaceOrientationMaskPortrait;

}

...

@end

Solution 14 - Iphone

my solution : subclassed UINavigationController and set it as window.rootViewController

the top viewcontroller of the hierarchy will take control of the orientation , some code examples : subclassed UINavigationController

Solution 15 - Iphone

The answers here pointed me in the correct direction although I couldn't get it to work by just cut and pasting because I am using UINavigationControllers inside of a UITabBarController. So my version in AppDelegate.m looks something like this, which will work for UITabBarControllers, UINavigationControllers or UINavigationControllers within a UITabBarController. If you are using other custom containment controllers, you would need to add them here (which is kind of a bummer).

- (UIViewController*)terminalViewController:(UIViewController*)viewController
{
  if ([viewController isKindOfClass:[UITabBarController class]])
  {
    viewController = [(UITabBarController*)viewController selectedViewController];
    viewController = [self terminalViewController:viewController];
  }
  else if ([viewController isKindOfClass:[UINavigationController class]])
  {
    viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
  }
  
  return viewController;
}

- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
  NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
  UIViewController* viewController = [self terminalViewController:window.rootViewController];

  if (viewController)
    orientations = [viewController supportedInterfaceOrientations];

  return orientations;
}

Another key thing to note is that you must override supportedInterfaceOrientations in your UIViewController subclasses or it will default to what you specified in your Info.plist.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaneuryzmView Question on Stackoverflow
Solution 1 - IphoneMartinView Answer on Stackoverflow
Solution 2 - IphoneNSStudentView Answer on Stackoverflow
Solution 3 - IphonePavelView Answer on Stackoverflow
Solution 4 - IphoneJames JonesView Answer on Stackoverflow
Solution 5 - IphonePhilView Answer on Stackoverflow
Solution 6 - IphoneCausaelityView Answer on Stackoverflow
Solution 7 - Iphoneuser1601259View Answer on Stackoverflow
Solution 8 - IphonetcdView Answer on Stackoverflow
Solution 9 - IphoneVassilyView Answer on Stackoverflow
Solution 10 - IphoneKubbaView Answer on Stackoverflow
Solution 11 - IphoneVarun BhatiaView Answer on Stackoverflow
Solution 12 - IphoneborrrdenView Answer on Stackoverflow
Solution 13 - IphoneY.MuranakaView Answer on Stackoverflow
Solution 14 - IphoneCarinaView Answer on Stackoverflow
Solution 15 - IphoneRay FixView Answer on Stackoverflow