How to programmatically set device orientation in iOS 7?

I am working on an iPad application using AutoLayout, where if the user turns on a certain mode (head-up mode), I want to support only portrait (or portrait upside down) orientation and, moreover, if the device is in landscape, I I would like to automatically switch to portrait mode.

In the top view controller, I have the following:

- (NSUInteger) supportedInterfaceOrientations { if (self.modeHeadsUp) { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; } else { return UIInterfaceOrientationMaskAll; } } - (BOOL) shouldAutorotate { return TRUE; } 

Based on the answers I saw elsewhere here, it seems that I should use "application setStatusBarOrientation". Therefore, in the method in which the user selected the one-on-one mode, I turned on:

  UIApplication *application = [UIApplication sharedApplication]; [application setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES]; 

However, it just does nothing. Although I can physically move the device so that it rotates into a portrait position, it does not do this automatically.

In fact, when in landscape mode, after running the above code, trying to programmatically set the orientation, when I request the application "statusBarOrientation" with the following code, it remains at "4" for landscape:

 UIApplication *application = [UIApplication sharedApplication]; int orientation = [application statusBarOrientation]; self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation]; 

It seemed like autolayout might not start using setStatusBarOrientation, so I tried adding this code after, but to no avail:

  [super updateViewConstraints]; [self.view updateConstraints]; 

I understand that Apple wants to leave the orientation of the device in the hands of the user. However, I would like to be able to maintain landscape mode when not in a one-on-one mode.

Am I missing something to make me change my orientation?

+70
ios xcode autolayout ios7
Jan 08
source share
18 answers

For iOS 7 and 8:

Objective-C:

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

Swift 3+:

 let value = UIInterfaceOrientation.landscapeLeft.rawValue UIDevice.current.setValue(value, forKey: "orientation") 

I call it in - viewDidAppear:

+190
Jan 08 '14 at 4:52
source share

Use this. The ideal solution to the orientation problem..ios7 and earlier

 [[UIDevice currentDevice] setValue: [NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; 
+20
Aug 27 '14 at 12:36 on
source share

You need to call attemptRotationToDeviceOrientation (UIViewController) so that the system calls your supportedInterfaceOrientations when the condition has changed.

+10
Jan 08 '14 at 5:03
source share

This works for me on Xcode 6 and 5.

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return (UIInterfaceOrientationMaskPortrait); } 
+4
Oct 12 '14 at 1:37
source share
 NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 

works, but you should return shouldAutorotate with YES in your view controller

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

But if you do, your VC will autorotate if the user rotates the device ... so I changed it to:

 @property (nonatomic, assign) BOOL shouldAutoRotate; - (BOOL)shouldAutorotate { return self.shouldAutoRotate; } 

and i call

 - (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation { self.rootVC.shouldAutoRotate = YES; NSNumber *value = [NSNumber numberWithInt: orientation]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; } 

to force a new orientation by pressing a button. To cancel shouldAutoRotate to NO, I added to my rootVC

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { self.shouldAutoRotate = NO; } 

PS: This workaround really works in all simulators.

+4
Apr 6 '15 at 13:02
source share

The only way that worked for me was to create a dummy modal view controller.

 UIViewController* dummyVC = [[UIViewController alloc] init]; dummyVC.view = [[UIView alloc] init]; [self presentModalViewController:dummyVC animated:NO]; [self dismissModalViewControllerAnimated:NO]; 

Your VC will request updated interface orientations when the modal view manager rejects.

It is curious that the UINavigationController does exactly this when it clicks / displays child view controllers with various supported interface orientations (tested on iOS 6.1, 7.0).

+3
Apr 02 '14 at 9:41
source share

This solution allows you to force a certain orientation of the interface by temporarily overriding the value UIDevice.current.orientation and then asking the system to rotate the interface in accordance with the rotation of the device:

Important: this is hacking and may stop working at any time

Add the application to the root application controller:

 class RootViewController : UIViewController { private var _interfaceOrientation: UIInterfaceOrientation = .portrait override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) } override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation } override func viewDidLoad() { super.viewDidLoad() // Register for notifications NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) { guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return } _interfaceOrientation = interfaceOrientation // Set device orientation // Important: // • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does // • This is a hack, and could stop working at any moment UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation") // Rotate the interface to the device orientation we just set UIViewController.attemptRotationToDeviceOrientation() } } private extension UIInterfaceOrientationMask { init(from interfaceOrientation: UIInterfaceOrientation) { switch interfaceOrientation { case .portrait: self = .portrait case .landscapeLeft: self = .landscapeLeft case .landscapeRight: self = .landscapeRight case .portraitUpsideDown: self = .portraitUpsideDown case .unknown: self = .portrait } } } extension Notification.Name { static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested") } 

Ensure that all interface orientations are marked in the Deployment Information section:

Interface orientation

Request interface orientation changes where you need them:

 NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight) 
+3
Mar 22 '17 at 0:26
source share

If you want to block the main view of your application in portraiture, but want to open pop-ups in landscape orientation, and you use tabBarController as rootViewController, like me, you can use this code in AppDelegate.

AppDelegate.h

 @interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UITabBarController *tabBarController; @end 

AppDelegate.m

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Create a tab bar and set it as root view for the application self.tabBarController = [[UITabBarController alloc] init]; self.tabBarController.delegate = self; self.window.rootViewController = self.tabBarController; ... } - (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController { return UIInterfaceOrientationMaskPortrait; } - (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController { return UIInterfaceOrientationPortrait; } 

It works very well.

In your viewController, which you want to represent in the landscape, you simply use the following:

 - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } - (BOOL)shouldAutorotate { return YES; } 
+2
Mar 07 '14 at 14:37
source share
  • Add this statement to AppDelegate.h

     //whether to allow cross screen marker @property (nonatomic, assign) allowRotation BOOL; 
  • Write this section of code in AppDelegate.m

     - (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window { If (self.allowRotation) { UIInterfaceOrientationMaskAll return; } UIInterfaceOrientationMaskPortrait return; } 
  • Change the allowRotation property of the allowRotation application

+2
Jun 29 '16 at 2:51
source share

If you have a UIViewController that should remain in portrait mode, just add this override and everything will be set.

 override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { return UIInterfaceOrientationMask.Portrait } 

The best part is the animation, when this view is displayed, it is already in the correct orientation.

+2
Aug 04 '16 at 17:49
source share

The base UINavigationController must have the following callback so that the children can decide which orientation they want.

 -(NSUInteger)supportedInterfaceOrientations { UIViewController *topVC = self.topViewController; return topVC.supportedInterfaceOrientations; } -(BOOL)shouldAutorotate { UIViewController *topVC = self.topViewController; return [topVC shouldAutorotate]; } 
+1
Apr 28 '15 at 9:02
source share

If you want only portrait mode, in iOS 9 (Xcode 7) you can:

  • Going to Info.plist
  • Select "Supported Landmarks"
  • Delete "Landscape (left button of the house)" and "Landscape (right button of the house)"

enter image description here

+1
Feb 29 '16 at 15:09
source share

I had a similar problem than yours. I need to block device orientation for some screens (e.g. Login) and allow rotation in others.

After a few changes and subsequent answers below, I did this:

  • Include all orientations in Project Info.plist.

enter image description here

  • Disabling orientation in those ViewControllers where I need to prevent the device from spinning, for example, on the "Login" screen in my case. I needed to override the shouldAutorotate method in this VC:

-(BOOL)shouldAutorotate{ return NO; }

Hope this works for you.

+1
May 03 '16 at 7:45 pm
source share

here is an example of FULL WORKING for iOS 7, 8, 9, 10, how to change the orientation of the application to its current opposite.

Objective-c

 - (void)flipOrientation { NSNumber *value; UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if(UIInterfaceOrientationIsPortrait(currentOrientation)) { if(currentOrientation == UIInterfaceOrientationPortrait) { value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]; } else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; } } else { if(currentOrientation == UIInterfaceOrientationLandscapeRight) { value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; } else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft) { value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]; } } [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; [UIViewController attemptRotationToDeviceOrientation]; } 

Swift 3

 func flipOrientation() -> Void { let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation var value : Int = 0; if(UIInterfaceOrientationIsPortrait(currentOrientation)) { if(currentOrientation == UIInterfaceOrientation.portrait) { value = UIInterfaceOrientation.portraitUpsideDown.rawValue } else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown) { value = UIInterfaceOrientation.portrait.rawValue } } else { if(currentOrientation == UIInterfaceOrientation.landscapeRight) { value = UIInterfaceOrientation.landscapeLeft.rawValue } else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft) { value = UIInterfaceOrientation.landscapeRight.rawValue } } UIDevice.current.setValue(value, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } 
+1
Jul 19 '17 at 13:24
source share

Try this with your code.

 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

after the user selects any option, then call this method because the user can be in landscape mode, and then he can only set portrait mode in the same view controller, so the view should automatically be moved to portrait mode, therefore in this acton button call it

 -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
0
Jan 08 '14 at 4:53
source share

It worked fine for me ....

 NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 
0
Feb 01 '18 at 12:10
source share

https://www.youtube.com/watch?v=d7QFtyow7TU This video helps you set the screen orientation in xcode

0
Jan 18 '19 at 16:44
source share

For people like me who struggled to get @Sunny Shah to accept the answer to work on the iPad. You need to check the box "Full screen required" in the project settings. Please note that this will prevent your application from multitasking, which may or may not be acceptable.

enter image description here

0
Apr 10 '19 at 3:29
source share



All Articles