UIDeviceOrientationFaceUp - how to distinguish between portrait and landscape?

I make this code skeleton for dealing with wanted & unwanted devices orientations, in my case i want to ignore the UIDeviceOrientationUnknown, UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown, caching the last allowed orientation. This code deals with iPhone and iPad devices and can be useful for you.

- (void)modXibFromRotation {

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    NSString *device = [[UIDevice currentDevice]localizedModel];
    UIInterfaceOrientation cachedOrientation = [self interfaceOrientation];

    if ([device isEqualToString:@"iPad"]) {

        if (orientation == UIDeviceOrientationUnknown || 
            orientation == UIDeviceOrientationFaceUp || 
            orientation == UIDeviceOrientationFaceDown) {

                orientation = (UIDeviceOrientation)cachedOrientation;
        }

        if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {

            /* Your code */
        }

        if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {

            /* Your code */     
        }
    }

    if ([device isEqualToString:@"iPhone"] || [device isEqualToString:@"iPod"]) {

        if (orientation == UIDeviceOrientationUnknown || 
        orientation == UIDeviceOrientationFaceUp || 
        orientation == UIDeviceOrientationFaceDown) {

            orientation = (UIDeviceOrientation)cachedOrientation;
        }

        if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {

             /* Your code */
        }

        if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {

            /* Your code */
        }
    }
}

As of iOS13 use

UIInterfaceOrientation orientation;
if (@available(iOS 13.0, *)) {
    orientation = self.window.windowScene.interfaceOrientation;
} else {
    orientation = [[UIApplication sharedApplication] statusBarOrientation];
}

You should not confuse UIDeviceOrientation and UIInterfaceOrientation, they are different but related as shown by their declaration

typedef enum {
   UIDeviceOrientationUnknown,
   UIDeviceOrientationPortrait,
   UIDeviceOrientationPortraitUpsideDown,
   UIDeviceOrientationLandscapeLeft,
   UIDeviceOrientationLandscapeRight,
   UIDeviceOrientationFaceUp,
   UIDeviceOrientationFaceDown
} UIDeviceOrientation;

typedef enum {
   UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
   UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
   UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
   UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
} UIInterfaceOrientation;

UIDeviceOrientation tells you what the orientation of the device is. UIInterfaceOrientation tells you what the orientation of your interface is, and is used by UIViewController. UIInterfaceOrientation will clearly be either portrait or landscape, whereas UIDeviceOrientation can have ambiguous values (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown, UIDeviceOrientationUnknown).

In any case you should not attempt to determine the orientation of a UIViewController with [[UIDevice currentDevice] orientation], as no matter what the device orientation is the UIViewController interfaceOrientation property can be different (for example if your app does not rotate to landscape at all [[UIDevice currentDevice] orientation] can be UIDeviceOrientationLandscapeLeft while viewController.interfaceOrientation can be UIInterfaceOrientationPortrait).

Update: As of iOS 8.0, [UIViewController interfaceOrientation] is deprecated. An alternative offered here is [[UIApplication sharedApplication] statusBarOrientation]. This also returns UIInterfaceOrientation.