UINavigationController Force Rotate

18,106

Solution 1

I had the same requirement for one of my applications!!!

luckily I found a solution!

In order to keep main viewcontroller landscape, no matter from what orientation it was popped/pushed, I did the following thing: (in viewWillAppear:)

//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];

//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];

P.S.Tested on sdk 3.2.5 ios 5.0.1.

P.S. On iOS 8 previous answer results some screen flickering and also - it is not stable (In some cases It does not work for me anymore.) So, for my needs, I changed the code to: (ARC)

//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];

[self.navigationController presentViewController:[UIViewController new] animated:NO completion:^{
    dispatch_after(0, dispatch_get_main_queue(), ^{
        [self.navigationController dismissViewControllerAnimated:NO completion:nil];
    });
}];

//I added this code in viewDidDissapear on viewController class, which will be popped back.

Hopefully it will help!

Solution 2

This might help. You can call the following method upon appearing, where appropriate. e.g. in -viewWillAppear:animated

attemptRotationToDeviceOrientation Attempts to rotate all windows to the orientation of the device.

+ (void)attemptRotationToDeviceOrientation

Discussion

Some view controllers may want to use app-specific conditions to determine the return value of their implementation of the shouldAutorotateToInterfaceOrientation: method. If your view controller does this, when those conditions change, your app should call this class method. The system immediately attempts to rotate to the new orientation. A rotation occurs so long as each relevant view controller returns YES in its implementation of the shouldAutorotateToInterfaceOrientation: method.

Availability

Available in iOS 5.0 and later. http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIViewController_Class/Reference/Reference.html

Solution 3

Use this,

[[UIDevice currentDevice]performSelector:@selector(setOrientation:) withObject:(__bridge id)((void *)UIInterfaceOrientationLandscapeRight)];
Share:
18,106
Zac Altman
Author by

Zac Altman

Updated on June 06, 2022

Comments

  • Zac Altman
    Zac Altman about 2 years

    My application is primarily portrait, however there is one view that REQUIRES a landscape orientation.

    My views are contained within a UINavigationController, which (apparently) is the cause of this issue.

    All UIViewControllers except one have this:

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

    The UIViewController that requires Landscape has this:

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

    Now, what happens is when the user reaches the landscape UIViewController, it is shown in portrait. The user can then rotate their phone and it displays in landscape as I want it to (locking to landscape). The user then progresses onwards to a portrait UIViewController and the same happens: it start in landscape, then they rotate their phone and it becomes portrait again (and locks to portrait).

    It seems orientation locking is allowed between UIViewControllers, however auto-rotation / programmatically changing the orientation is somehow blocked.

    How do I force the phone to update to the correct orientation?

    There is a temporary solution: I can detect the orientation of the device and show a message asking them to rotate the device if it is not correct, however this is not optimal.

  • danh
    danh over 12 years
    wow +1 good tip (and another goody in os5). this problem has given me many hours of headache.
  • k06a
    k06a about 12 years
    Works on iOS6beta1. Thank you!
  • shim
    shim over 11 years
    There are all kinds of functions to set the autorotation settings there, but they don't seem to be consistently called. I put -(BOOL) shouldAutorotate { return NO; } But this never got called.
  • Martin Berger
    Martin Berger over 11 years
    For me, with UINavigationController, this approach fails because although status bar do rotates, interface still remains. So user must rotate it once more to set the interface.
  • Guntis Treulands
    Guntis Treulands over 11 years
    Yes, I myself had a situation where this trick didn't work after all. That means, that your application's functionality (element autoresizing or too deep view/subview integration or probably something else) is not allowing this feature to work. sorry. In simple cases it helps.
  • Guntis Treulands
    Guntis Treulands about 11 years
    In viewcontroller, which needs specific rotation.
  • Mangesh
    Mangesh about 11 years
    It crash my app. I am using this when movie player dissmiss.
  • Guntis Treulands
    Guntis Treulands about 11 years
    I am not sure whether it works on modal viewcontroller dismissing. Maybe problem is elsewhere? If You are targeting iOS >= 5.0 - try stackoverflow.com/a/9827763/894671
  • TJez
    TJez over 10 years
    Non-deprecated methods (ios 7): [self presentViewController:mVC animated:NO completion:nil]; and [self dismissViewControllerAnimated:NO completion:nil];
  • Bulla
    Bulla over 10 years
    Above code worked for me, but it does not seems to be appropriate. And there is minor change in above code, which i have improved. UIViewController *mVC = [[UIViewController alloc] init]; [self presentViewController:mVC animated:NO completion:nil]; [[mVC presentingViewController] dismissViewControllerAnimated:YES completion:nil]; mVC = nil;
  • PokerIncome.com
    PokerIncome.com about 10 years
    This trick works for forcing the orientation. However, all my views are removed from the view controller and it's showing blank page except for the top navigation bar and bottom tab bar.
  • Shaun Budhram
    Shaun Budhram almost 10 years
    Flashes the screen on iOS8. Is there not a more elegant solution?
  • Aist Marabu
    Aist Marabu over 9 years
    I have the same problem on iOS8 (flashes). In my situation, I need change device rotation during subview transitions. To reduce this flash effect, I have changed background color of presented view to white.
  • Yucel Bayram
    Yucel Bayram over 9 years
    It actually did not work, all view suddenly disappear and only white page with Back button on top(UINavigationController used)
  • MobileMon
    MobileMon almost 9 years
    works but i feel like it could break in future since its probably undocumented
  • Thangavel
    Thangavel almost 9 years
    No, it is apple native orientation. I have used this and got approved from apple for 2 of my apps.
  • Mihir Oza
    Mihir Oza almost 9 years
    In IOS 8.4 it takes some time. so a little bit flickering occur. any solution??
  • Mihir Oza
    Mihir Oza almost 9 years
    not working for me when device force rotate in Portrait mode after image capturing in landscape.
  • meisel
    meisel over 8 years
    Nicer way of writing it: [[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeLeft) forKey:@"orientation"]
  • joehanna
    joehanna over 7 years
    Awesome - so good! This has eluded me for years! Thanks so much