How to force or disable interface orientation for some but not all UIViewController?

12,772

Solution 1

Try to subclass the UINavigationController you are using because the default UINavigationController is not forwarding the shouldAutorotate method to you viewcontroller.

Implement the following method in your UINavigationController subclass

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

Now the UINavigationController forwards the method call to its current visible UIViewController so you need to implement shouldAutorotate there individually to get your desired effect.

Solution 2

Try adding this method along with shouldAutorotate and supportedInterfaceOrientations

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    //Setting the orientation of the view.  I've set it to portrait here.
    return UIInterfaceOrientationPortrait;

}

Also you can use this [UIViewController attemptRotationToDeviceOrientation] So that it rotates to the desired new orientation

Solution 3

Your PortraitViewController is ok and I don't know your Storyboard configuration. In your case important thing is you should embedded your target view controller in another new navigation controller, then set it's class to your PortraitViewController and present that navigation modally, like I have done in below image and it's working as expected.

enter image description here

If you want to show animation that will make presentation animation like push animation

Below is mine PortrateNavigation subClass of UINavigationController

PortrateNavigation.h

#import <UIKit/UIKit.h>

@interface PortrateNavigation : UINavigationController

@end

PortrateNavigation.m

#import "PortrateNavigation.h"

@implementation PortrateNavigation

- (void)viewDidLoad  {
    [super viewDidLoad];
}

- (BOOL)shouldAutorotate {
    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

@end

Solution 4

Create a category on the UINavigationController and override supportedInterfaceOrientations

#import "UINavigationController+Orientation.h"

 @implementation UINavigationController (Orientation)

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

-(BOOL)shouldAutorotate
 {
    return YES;
 }

@end  

When you Embedded UINavigationController, Containers don't ask their children whether to rotate or not

Solution 5

Tr this in your view controller

- (BOOL)shouldAutorotate{
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationPortrait |
           UIInterfaceOrientationPortraitUpsideDown;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationPortrait;
}
Share:
12,772
TechChain
Author by

TechChain

I have 4+ of experience of overall experience.Currently working on Hyperledger Fabric blockchain framework. I have strong knowledge of Objective c, Swift.I have developed lot of apps from chat app, finance apps,location &amp; map based apps.

Updated on June 24, 2022

Comments

  • TechChain
    TechChain almost 2 years

    I have an app with 9-10 screens. I embedded a UINavigationController into my view controller. I have few view controllers which I want set only portrait orientation: it means that rotating the device should not rotate these view controllers to landscape mode. I have tried the following solutions:

    first:

       NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
       [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    

    but screen still rotates to landscape.

    Second: I created a custom view controller class as PortraitViewController and added the code below in PortraitViewController.m

    @interface PortraitViewController ()
    @end
    
    @implementation PortraitViewController
    - (BOOL)shouldAutorotate
    {
        return YES;
    }
    
    - (NSUInteger)supportedInterfaceOrientations
    {
        //Here check class name and then return type of orientation
        return UIInterfaceOrientationMaskPortrait;
    }
    @end
    

    After that I implemented PortraitViewController.h as a base class

    #import <UIKit/UIKit.h>
    #import "PortraitViewController.h"
    @interface Login : PortraitViewController
    @end
    

    It does not work at all, still allows view controller to rotate in landscape mode.

    Is there any other solution i am using iOS 8 & don't want viewcontroller to rotate in landscape mode?

    EDIT: Is it possible to have Landscape orientation only for some view controllers, and force other view controllers orientation to stick to Portrait?

  • TechChain
    TechChain almost 9 years
    Do i need to set some delegate for using this method?
  • VRAwesome
    VRAwesome almost 9 years
    No need to set delegate, it's UIViewController class method.
  • Klinkert0728
    Klinkert0728 almost 9 years
    If the view is embed in a uinavigation controller you should subclass the navigation and in your custom navigation controller write that code
  • dakab
    dakab almost 9 years
    A short explanation would improve your answer.
  • Charlie Scott-Skinner
    Charlie Scott-Skinner over 7 years
    Shouldn't the return type of 'supportedInterfaceOrientationsForWindow:' be 'UIInterfaceOrientationMask' instead of 'NSUInteger'?
  • Manish Verma
    Manish Verma over 7 years
    @CharlieScott-Skinner Yes. You can write it there. But as the definition suggests 'typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask)' you can also type NSUInteger.