iOS 6: how to force change orientation when pushing view controller into the navigation controller stack

18,282

Solution 1

I am also find the same problem.i have found that shouldAutorotate function not call every time so i change orientation programmatic

first import this

#import <objc/message.h>

then

-(void)viewDidAppear:(BOOL)animated
{

     if(UIDeviceOrientationIsPortrait(self.interfaceOrientation)){
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
        {
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationLandscapeLeft );


        }
    }

}

hope this help you.

Solution 2

Add new Objective-C class (subclass of UINavigationController) and add the following code to the .m files

-(NSUInteger)supportedInterfaceOrientations
 {
     NSLog(@"supportedInterfaceOrientations = %d ", [self.topViewController         supportedInterfaceOrientations]);

     return [self.topViewController supportedInterfaceOrientations];
 }

-(BOOL)shouldAutorotate
  {
     return self.topViewController.shouldAutorotate;
  }

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
    // You do not need this method if you are not supporting earlier iOS Versions

    return [self.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
  }

After you added the new classes go to your ViewController classes and make the following changes

- (BOOL)shouldAutorotate  // iOS 6 autorotation fix
  {
    return YES;
  }
- (NSUInteger)supportedInterfaceOrientations // iOS 6 autorotation fix
  {
      return UIInterfaceOrientationMaskAll;
  }

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation // iOS 6 autorotation fix
  {
      return UIInterfaceOrientationPortrait;
  }
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
  {
      return YES;
  }

enter image description here

In the shouldAutorotate , shouldAutorotateToInterfaceOrientation: return YES if you want the ViewController to be supporting Multiple orientation else return NO , also in houldAutorotateToInterfaceOrientation: method pass the Orintation you want for that specific ViewController , Repeat the same for all the view controllers .

Reason of doing this:-

1:Although you can change the preferredInterfaceOrientationForPresentation: of any viewController to a specific orientation but since you are using the UINavigationController you also need to override the supportedInterfaceOrientations for your UINavigationController

2:In order the override the supportedInterfaceOrientations for UINavigationController we have subclassed UINavigationController and modified the method related to the UINavigation Orientation.

Hope it will help you !

Solution 3

Make the app support only portrait mode and add the following line to the initWithNibName of UIViewController 2

self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
Share:
18,282
ymotov
Author by

ymotov

Updated on June 04, 2022

Comments

  • ymotov
    ymotov almost 2 years

    I think this question should've been asked a million times by now, but I still can't find an answer to this.

    Here's my hierarchy: UINavigationController -> UIViewController 1 ->(push)-> UIViewController 2

    UINavigationController: supports all possible orientation UIViewController 1: supports only portrait UIViewController 2: supports only landscape

    How can I lock UIViewController 1 into portrait only and at the same time lock UIViewController 2 into landscape only? Is it even possible? So far what I see is that UIViewController 2 always takes the orientation of UIViewController 1.

    Note, that this is for iOS 6 only.

    Thanks!

    • yen
      yen about 11 years
      Try this It will work for you : stackoverflow.com/questions/12520030/…
    • matt
      matt about 11 years
      You can't find an answer because it can't be done. Despite all the answers below, what you are asking to do is simply not supported in iOS 6. iOS 6 allows response to user rotation of the device, but not forced rotation. The only way to force rotation in iOS 6 is to use a presented view controller, not a view controller pushed onto the navigation controller stack.
    • matt
      matt about 11 years
      You can, however, construct a presented view controller in such a way that it looks as if it were part of the same navigation interface. And since a presented view controller can force rotation both when presenting and dismissing, this effectively solves the problem. See, for example, my answer here: stackoverflow.com/a/4103137/341994
    • matt
      matt about 11 years
      I have made a movie showing what I mean: youtu.be/O76d6FhPXlE As you can see, it sort of looks like I'm pushing a second view onto the navigation controller and forcing rotation. But in reality there are two navigation controllers; the second one is presented (modal), so I am able to force rotation when it appears and when it is dismissed.
    • ymotov
      ymotov about 11 years
      Thanks @matt. That totally explains why everything I tried so far just doesn't work. Especially huge thank you for the your effort explaining in details and even creating a short movie. Super helpful!! Since I can't mark your comment as accepted answer I just up-voted your comment.
  • BootMaker
    BootMaker almost 11 years
    It's cleaner and easier to attach it as a category to AppDelegate then make a new class just for this, but it's working both way.
  • Martin
    Martin over 10 years
    setOrientation is an undocumented method, using it can be cause for dismissal of your app from the AppStore. Use at your own risk.
  • Sumit Mundra
    Sumit Mundra over 10 years
    no its not true. I am also use this method in my app and this is live on app store.
  • TheCodingArt
    TheCodingArt over 10 years
    Apple used to have a public read write property for orientation available. They changed it to read only. The above is a dangerous trick providing you access to their private setter. This very well can lead to your app being rejected. In your case it didn't, but use this at your own risk.
  • Nishant Tyagi
    Nishant Tyagi over 10 years
    +1 for this nice answer. This is a suitable way for rotation.
  • skywinder
    skywinder over 10 years
    Finally! Thank you! Clear and simple!
  • user726522
    user726522 over 10 years
    that causes the rotation of the interface as you want, but don't forget to switch back right after or else device will think it's in wrong orientation by adding this right in the second line: objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), _yourRealInterfaceOrientation );
  • adsurbum
    adsurbum over 10 years
    great! working and nice solution
  • adsurbum
    adsurbum over 10 years
    hmm..no. It is not working properly. Don't know how i checked it yesterday, but on clicking back button the parent view controller gets son's orientation
  • NightFury
    NightFury about 10 years
    this is not change of orientation.