I have a question on how to detect the device orientation on iOS. I don't need to receive change notifications, just the current orientation itself. This seems to be a rather simple question, but I haven't been able to wrap my head around it. Below is what I have done so far:
UIDevice *myDevice = [UIDevice currentDevice] ;
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation deviceOrientation = myDevice.orientation;
BOOL isCurrentlyLandscapeView = UIDeviceOrientationIsLandscape(deviceOrientation);
[myDevice endGeneratingDeviceOrientationNotifications];
In my mind this should work. I enable the device to receive device orientation notices, then ask for what orientation it is in, but then it is not working and I don't know why.
Really old thread, but no real solution.
I Had the same problem, but found out that getting The UIDeviceOrientation isn't always consistent, so instead use this:
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(orientation == 0) //Default orientation
//UI is in Default (Portrait) -- this is really a just a failsafe.
else if(orientation == UIInterfaceOrientationPortrait)
//Do something if the orientation is in Portrait
else if(orientation == UIInterfaceOrientationLandscapeLeft)
// Do something if Left
else if(orientation == UIInterfaceOrientationLandscapeRight)
//Do something if right
if UIViewController:
if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
//
}
if UIView:
if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
//
}
UIDevice.h:
#define UIDeviceOrientationIsPortrait(orientation) ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown)
#define UIDeviceOrientationIsLandscape(orientation) ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight)
Updated:
add this code to xxx-Prefix.pch then you can use it anywhere:
// check device orientation
#define dDeviceOrientation [[UIDevice currentDevice] orientation]
#define isPortrait UIDeviceOrientationIsPortrait(dDeviceOrientation)
#define isLandscape UIDeviceOrientationIsLandscape(dDeviceOrientation)
#define isFaceUp dDeviceOrientation == UIDeviceOrientationFaceUp ? YES : NO
#define isFaceDown dDeviceOrientation == UIDeviceOrientationFaceDown ? YES : NO
usage:
if (isLandscape) { NSLog(#"Landscape"); }
For what You looking for first you have to Get Notification if Orientation Changed!
You Can set This Thing in viewDidLoad like
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
and whenever Orientation of your Device changed OrientationDidChange Called where You can do whatever You Want as Per Orientation
-(void)OrientationDidChange:(NSNotification*)notification
{
UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];
if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight)
{
}
else if(Orientation==UIDeviceOrientationPortrait)
{
}
}
If you want to get device orientation directly from accelerometer use [[UIDevice currentDevice] orientation]. But if you need current orientation of your application(interface orientation) use [[UIApplication sharedApplication] statusBarOrientation].
UIViewController has an interfaceOrientation property that you can access to find out the current orientation of a view controller.
As for your example, that should work. When you say it isn't working, what do you mean? What results does it give you versus what you expected?
In Swift 3.0
to get device orientation.
/* return current device orientation.
This will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.
*/
UIDevice.current.orientation
to get device orientation from your app
UIApplication.shared.statusBarOrientation
Wasn't satisfied by "UIDeviceOrientation" because when a UIViewcontroller orientation is fixed to a specific orientation you don't get a pertinent information with the device orientation, so the right thing to do is using "UIInterfaceOrientation".
You can get the orientation from the UIViewController with a "self.interfaceOrientation", but when you are factorizing our code, you might need to do this kind of test outside a view controller, (custom view, a category…), so you still can access the information anywhere outside the controller by using the rootviewController:
if (UIInterfaceOrientationIsLandscape(view.window.rootViewController.interfaceOrientation)) {
}
There's a way to achieve this whether the orientation lock is enabled or not by using data from CoreMotion.
This is the code:
#import <CoreMotion/CoreMotion.h>
CMMotionManager *cm=[[CMMotionManager alloc] init];
cm.deviceMotionUpdateInterval=0.2f;
[cm startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *data, NSError *error) {
if(fabs(data.gravity.x)>fabs(data.gravity.y)){
NSLog(#"LANSCAPE");
if(data.gravity.x>=0){
NSLog(#"LEFT");
}
else{
NSLog(#"RIGHT");
}
}
else{
NSLog(#"PORTRAIT");
if(data.gravity.y>=0){
NSLog(#"DOWN");
}
else{
NSLog(#"UP");
}
}
}];
Have you unlocked the hardware lock for device orientation? There is one at the edge of my iPad 1.
Here is some Swift variables to make detection easier:
let LANDSCAPE_RIGHT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight
let LANDSCAPE_LEFT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft
let LANDSCAPE: Bool = LANDSCAPE_LEFT || LANDSCAPE_RIGHT
let PORTRAIT_NORMAL: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait
let PORTRAIT_REVERSE: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.PortraitUpsideDown
let PORTRAIT: Bool = PORTRAIT_REVERSE || PORTRAIT_NORMAL
My current way of doing this:
+ (BOOL)isPortrait {
let window = UIApplication.sharedApplication.delegate.window;
if(window.rootViewController) {
let orientation =
window.rootViewController.interfaceOrientation;
return UIInterfaceOrientationIsPortrait(orientation);
} else {
let orientation =
UIApplication.sharedApplication.statusBarOrientation;
return UIInterfaceOrientationIsPortrait(orientation);
}
}
If there is for some reason no rootViewController yet fail safe to statusBarOrientation...
And the best reliable way in swift :
public extension UIScreen {
public class var isPortrait: Bool {
UIApplication.shared.delegate?.window??.rootViewController?.interfaceOrientation.isPortrait ??
UIApplication.shared.statusBarOrientation.isPortrait
}
public class var isLandscape: Bool { !isPortrait }
}
This is my solution with Combine, which is quite easy to use with SwiftUI or regular Swift Object. A singleton object (static instance) is better than the "environment" for this kind of truly global object.
// Singleton object to keep the interface orientation (and any other global state)
class SceneContext: ObservableObject {
#Published var interfaceOrientation = UIInterfaceOrientation.portrait
static let shared = SceneContext()
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
...
func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {
SceneContext.shared.interfaceOrientation = windowScene.interfaceOrientation
}
}
// if you want to execute some code whenever the orientation changes in SwiftUI
someView {
....
}
.onReceive(SceneContext.shared.$interfaceOrientation) { (orientation) in
// do something with the new orientation
}
// if you want to execute some code whenever the orientation changes in a regular Swift object
let pub = SceneContext.shared.$interfaceOrientation.sink(receiveValue: { (orientation) in
// do something with the new orientation
...
})
Related
What is the objc code for below swift statement?
if (UIDevice.currentDevice().orientation.isLandscape)
what i figured out so far is
if ([[UIDevice currentDevice] orientation])
From apple Docs:-
BOOL UIDeviceOrientationIsLandscape(UIDeviceOrientation orientation);
Returns a Boolean value indicating whether the device is in a
landscape orientation.
So try this:-
if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
//True if landscape is on
}
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
BOOL isLandscape = UIDeviceOrientationIsLandscape(orientation);
if (isLandscape) {
NSLog(#"Landscape orientation")
//Do the work
}
Things are easy to handle if the user rotates the device (I handle the call of viewWillTransitionToSize), but the app has to know its initial orientation.
Until now, I have been using the status bar orientation and device orientation
if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
//
}
if (INTERFACE_IS_PHONE && UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation) ) {
//
}
UIInterfaceOrientation orientation = [UIDevice currentDevice].orientation;
if (INTERFACE_IS_PHONE && UIDeviceOrientationIsPortrait(orientation) ) {
//
}
above methods showing wrong orientation ,any ?
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.
The orientation property of UIDevice is an enum that does distinguish between landscape left and right (their values are 3 and 4 respectively), so you can check that value.
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
If you're showing what the camera is seeing, i would ignore all orientations and show the user a preview of what the devices sees in portrait. What they see will always be "correct", and never accidentally upside down.
You always can determine device orientation using gravity property of CMDeviceMotion class. Property return a normalized vector pointed to Earth center (aka real gravity vector). If you not interested in angles, you can test only signs and generate constants for your purpose.
This is how I have done it in the pass
Create a global variable called previousOr. Then in your first viewController use the following code to determine the status bar position. I put it in the viewDidAppear
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
previousOr = [NSString stringWithFormat:#"L"];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
previousOr = [NSString stringWithFormat:#"L"];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
previousOr = [NSString stringWithFormat:#"P"];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) {
previousOr = [NSString stringWithFormat:#"P"];
}
Then in your subsequent viewControllers you have the following in the ViewDidLoad methods, this will detect if the device is portrait or landscape or if the device is flat what the device was in before they placed it flat:
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
NSLog(#"landscape");
[self switchToLandscape];
}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
NSLog(#"portrait");
[self switchToPortrait];
}
else {
if ([previousOr isEqualToString:#"L"]) {
[self switchToLandscape];
}
else {
[self switchToPortrait];
}
}
Then you also have the following to do the re-plotting of elements on the view
- (void)switchToLandscape {
previousOr = [NSString stringWithFormat:#"L"];
//do stuff like replot centers
}
- (void)switchToPortrait {
previousOr = [NSString stringWithFormat:#"P"];
//do stuff like replot centers
}
and then you also have the following to detect the change in orientation:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
[self switchToLandscape];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
[self switchToLandscape];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
[self switchToPortrait];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) {
[self switchToPortrait];
}
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(BOOL) shouldAutorotate {
return YES;
}
NOTE; I put in both shouldAutorotateToInterfaceOrientation and shouldAutoRotate for backward compatibility.
Had face the same issue. here is the answer, always go for UIIntefaceOrientation to check whether current orientation is Landscape or Portrait.
OBJECTIVE C :
if([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationLandscapeRight)
{
//Go Here for landscape
}
else if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown)
{
//Go Here for Portrait
}
SWIFT :
let currentOrient : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
if currentOrient == UIInterfaceOrientation.landscapeLeft || currentOrient == UIInterfaceOrientation.landscapeRight
{
//Go Here for landscape
}
else if currentOrient == UIInterfaceOrientation.portrait || currentOrient == UIInterfaceOrientation.portraitUpsideDown
{
//Go Here for Portrait
}
I need to get device orientation from a ViewController. I cannot base on:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
because it sometimes returns orientation unknown (for example when the device lays on the table).
I just need to know in what orientation is my current UIView displayed (is it landscape left or landscape right). I don't need to have this value updated when orientation changes, I just want to know it, when I ask for it. Just some reference view.orientation ;). Is there something that would help me? I've read UIView documentation, found some reference to UIWindow, but nothing that could help me.
You can also get the device orientation from UIApplication, have you tried using
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
UIViewController has a property
UIInterfaceOrientation interfaceOrientation;
So in your UIViewController, you can access the current orientation of the device at any time via
UIInterfaceOrientation myCurrentOrientation = self.interfaceOrientation;
Swift Version
let currentOrientation:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
if currentOrientation.isPortrait {
print("PORTRAIT")
} else if currentOrientation.isLandscape {
print("LANDSCAPE")
}
Following is the sample code to do the same. There is a variable named deviceOrientation, and it will answer the current orientation of device, whenever being asked.
UIDeviceOrientation deviceOrientation;
- (void)viewWillAppear:(BOOL)animated
{
deviceOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation];
[self willAnimateRotationToInterfaceOrientation:deviceOrientation duration:0.5];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
deviceOrientation = (UIDeviceOrientation)interfaceOrientation;
if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
NSLog(#"Landscape");
}
else
{
NSLog(#"Portrait");
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return TRUE;
}
I have an app with a tab bar, and nav controllers in each tab. When user shakes the device, a UIImageView appears as a child view in the nav controller. But the UIImageView must contain a special image, depending on the device's current orientation.
If I write just
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
//Code
}
else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight||interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
//Code
}
}
The view just goes crazy if user rotated the device before shaking.
Is there a method to get iPhones current orientation?
Here are macros UIDeviceOrientationIsLandscape and UIDeviceOrientationIsPortrait
so rather checking separately you can do it like this ...
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
// code for landscape orientation
}
OR
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
// code for Portrait orientation
}
Use the [[UIDevice currentDevice] orientation] method, as specified here.
As beno said, this seems a better answer if you are detecting orientation early in your View. I couldn't get the approved answer to return a result early in my setup but this works wonderfully.
if (UIDeviceOrientationIsPortrait(self.interfaceOrientation)){
//DO Portrait
}else{
//DO Landscape
}
To addon to the already answered question:
You use [[UIDevice currentDevice] orientation] which will yield one of these values:
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
The documentation can be found here - (orientation) and here - (UIDeviceOrientation).
(I don't mean to claim the former anwser, but this information was to big for a comment.)
Try this:
[[UIApplication sharedApplication] statusBarOrientation]
Or in Swift 3:
UIApplication.shared.statusBarOrientation
To specifically check for a particular orientation you can also try the isLandscape or isPortrait property like so:
UIApplication.shared.statusBarOrientation.isLandscape
The problem with [[UIDevice currentDevice] orientation] is that it will also return UIInterfaceOrientationUnknown which statusBarOrientation does not.
There is also a UIViewController property interfaceOrientation but it was deprecated in iOS 8, so it's not recommended.
You check documentation for statusBarOrientation here
You can also use the interfaceOrientation property of the UIViewController class, if you are stuck and continuously getting UIDeviceOrientationUnknown from UIDevice.
There's a good summary of why [[UIDevice currentdevice] orientation] can sometimes fail here: http://bynomial.com/blog/?p=25, especially if you want to detect the orientation quickly (for example, if you wanted to check right when the app comes out of the background).
It helps you...
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft || [[UIDevice currentDevice] orientation ]== UIDeviceOrientationLandscapeRight)
{
NSLog(#"Lanscapse");
}
if([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown )
{
NSLog(#"UIDeviceOrientationPortrait");
}
}
As Simple Solution of Swift 4.2
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
switch UIDevice.current.orientation{
case .portrait:
print("Portrait")
case .portraitUpsideDown:
print("PortraitUpsideDown")
case .landscapeLeft:
print("LandscapeLeft")
case .landscapeRight:
print("LandscapeRight")
default:
print("Another")
}
}
You can also define constants to earn time :
#define LANDSCAPE UIInterfaceOrientationIsLandscape(self.interfaceOrientation)
#define LANDSCAPE_RIGHT [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft
#define LANDSCAPE_LEFT [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight
#define PORTRAIT UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
#define PORTRAIT_REVERSE [UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown
Updating this to iOS 8+ where the UIViewController.interfaceOrienation is deprecated, you should use traitCollections. So for example, to check for landscape on iPhone, you'd use:
if self.traitCollection.verticalSizeClass == .compact
{
your code
}
Notice that this is not the case on iPad, because on iPad in landscape, the size class is not compact.
Apple Doc Link
And if you simply want whether the device is in landscape or portrait, a simple solution is (in Swift):
var orientation = "portrait"
if UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height {
orientation = "landscape"
}
You could check it like so (Swift 3):
var isPortrait: Bool {
let orientation = UIDevice.current.orientation
switch orientation {
case .portrait, .portraitUpsideDown:
return true
case .faceUp, .faceDown:
// Check the interface orientation
let interfaceOrientation = UIApplication.shared.statusBarOrientation
switch interfaceOrientation{
case .portrait, .portraitUpsideDown:
return true
default:
return false
}
default: // .unknown
return false // not very satisfying to return false as if we were in landscape :-/
}
}
If you are in a ViewController, you can also do like so (that is what I ended up doing):
private var isPortrait: Bool {
let orientation = UIDevice.current.orientation
switch orientation {
case .portrait, .portraitUpsideDown:
return true
case .landscapeLeft, .landscapeRight:
return false
default: // unknown or faceUp or FaceDown
return self.view.width < self.view.height
}
}
Although even this should be enough in that case:
private var isPortrait: Bool {
return self.view.width < self.view.height
}
Swift 5
I got this from another SO answer about 4 yrs ago. I still use it to this day. I don't remember which answer otherwise I would link to it.
Anyway you can use the notification UIDevice.orientationDidChangeNotification:
override func viewDidLoad() {
super.viewDidLoad()
// add this to viewDidLoad
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil)
}
#objc func deviceOrientationDidChange() {
switch UIDevice.current.orientation {
case .landscapeRight:
print("landscapeRight")
case .landscapeLeft:
print("landscapeLeft")
case .portrait:
print("portrait")
case .faceUp:
print("faceUp")
case .faceDown:
print("faceDown")
case .portraitUpsideDown:
print("portraitUpsideDown")
case .unknown:
print("unknown")
default:
print("default")
}
}
Getting the current orientation
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"Landscape left");
self.lblInfo.text = #"Landscape left";
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
NSLog(#"Landscape right");
self.lblInfo.text = #"Landscape right";
} else if (orientation == UIInterfaceOrientationPortrait) {
NSLog(#"Portrait");
self.lblInfo.text = #"Portrait";
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
NSLog(#"Upside down");
self.lblInfo.text = #"Upside down";
}
}