I want to present a view that responds to orientation changes but for various reasons can't use iOS's built-in autorotation. In viewDidLoad
I use the current orientation to determine the initial layout of the view:
_originalOrientation = [UIDevice currentDevice].orientation;
// if we were launched flat or unknown, use the status bar orientation as a guide
if (_originalOrientation == UIDeviceOrientationUnknown ||
_originalOrientation == UIDeviceOrientationFaceDown ||
_originalOrientation == UIDeviceOrientationFaceUp) {
_originalOrientation = UIDeviceOrientationFromInterfaceOrientation([UIApplication sharedApplication].statusBarOrientation);
}
As you can see from my comment, I need to handle the case where [UIDevice currentDevice].orientation
is not a usable direction (i.e. the device is flat or in an unknown orientation). In this scenario, I attempt to use the statusBarOrientation
to infer the device's orientation (using UIViewController
's interfaceOrientation
would be an alternative way to get the same information):
UIDeviceOrientation UIDeviceOrientationFromInterfaceOrientation(UIInterfaceOrientation interface) {
// note: because UIInterfaceOrientationLandscapeLeft and UIInterfaceOrientationLandscapeRight have the same value, this conversion can't distinguish them
if (interface == UIInterfaceOrientationLandscapeLeft) {
return UIDeviceOrientationLandscapeLeft;
} else if (interface == UIInterfaceOrientationLandscapeRight) {
return UIDeviceOrientationLandscapeRight;
} else if (interface == UIInterfaceOrientationPortraitUpsideDown) {
return UIDeviceOrientationPortraitUpsideDown;
} else {
return UIDeviceOrientationPortrait;
}
}
However my logic can't accurately discern the two landscape cases because they are defined UIApplication.h
to be the same constant value:
// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
};
Is there an alternative way I can distinguish between UIInterfaceOrientationLandscapeLeft
and UIInterfaceOrientationLandscapeRight
? Is there a better way for me to perform my "fallback" logic besides using the status bar orientation?
You wrote:
However my logic can't accurately discern the two landscape cases because they are defined UIApplication.h to be the same constant value
I am pretty sure that they are not! The values for interface and device orientations are swapped. See UIApplication.h
:
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
};
The interface orientation UIInterfaceOrientationLandscapeLeft
is equal to the device orientation UIDeviceOrientationLandscapeRight
, and vice versa. But:
UIInterfaceOrientationLandscapeLeft != UIInterfaceOrientationLandscapeRight
UIDeviceOrientationLandscapeLeft != UIDeviceOrientationLandscapeRight
Try this code, I assume that will fix the problem:
UIDeviceOrientation UIDeviceOrientationFromInterfaceOrientation(UIInterfaceOrientation interface) {
// interface orientation left is device orientation right
if (interface == UIInterfaceOrientationLandscapeLeft) {
return UIDeviceOrientationLandscapeRight;
// interface orientation right is device orientation left
} else if (interface == UIInterfaceOrientationLandscapeRight) {
return UIDeviceOrientationLandscapeLeft;
} else if (interface == UIInterfaceOrientationPortraitUpsideDown) {
return UIDeviceOrientationPortraitUpsideDown;
} else {
return UIDeviceOrientationPortrait;
}
}
BTW, you should also consider to use an own prefix for your function instead of UI
, otherwise it may be easy to mistakenly assume that UIDeviceOrientationFromInterfaceOrientation
is an API function.