I am working on an iPad app, using AutoLayout, where if the user enables a certain mode ("heads-up" mode), I want to support only portrait (or portrait upside down) orientation, and furthermore, if the device is in landscape, I'd 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 answers I've seen elsewhere here, the answer seems to be that I should use "application setStatusBarOrientation". Therefore, in the method where the user has selected "heads-up" mode, I have included:
UIApplication *application = [UIApplication sharedApplication];
[application setStatusBarOrientation:UIInterfaceOrientationPortrait
animated:YES];
However, this simply doesn't seem to do anything. While I can physically move the device to get it to rotate into portrait, it doesn't do so automatically.
In fact, when in landscape mode after running the above code to attempt to programmatically set the orientation, when I query 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 maybe autolayout wasn't being triggered with the setStatusBarOrientation, so I attempted to add this code after, to no effect:
[super updateViewConstraints];
[self.view updateConstraints];
I realize Apple wants to leave device orientation in the hands of the user. However, I'd like to be able to support landscape mode when not in "heads-up" mode.
Am I missing something to be able to force orientation change?
This solution lets you force a certain interface orientation, by temporarily overriding the value of
UIDevice.current.orientation
and then asking the system to rotate the interface to match the device's rotation:Important: This is a hack, and could stop working at any moment
Add the following in your app's root view controller:
Make sure all interface orientations are checked under "Deployment Info":
Request interface orientation changes where you need them:
Use this. Perfect solution to orientation problem..ios7 and earlier
does work but you have to return shouldAutorotate with YES in your view controller
But if you do that, your VC will autorotate if the user rotates the device... so I changed it to:
and I call
to force a new orientation with a button-click. To set back shouldAutoRotate to NO, I added to my rootVC
PS: This workaround does work in all simulators too.
The base UINavigationController should have the below callback so that the child items can decide what orientation they want.
I was in a similar problem than you. I need to lock device orientation for some screens (like Login) and allow rotation in others.
After a few changes and following some answers below I did it by:
shouldAutorotate
method in this VC:-(BOOL)shouldAutorotate{ return NO; }
Hope this will work for you.
You need to call
attemptRotationToDeviceOrientation (UIViewController)
to make the system call yoursupportedInterfaceOrientations
when the condition has changed.