72

我有一个关于如何在 iOS 上检测设备方向的问题。我不需要接收更改通知,只需要接收当前方向本身。这似乎是一个相当简单的问题,但我一直无法理解它。以下是我到目前为止所做的:

UIDevice *myDevice = [UIDevice currentDevice] ;
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation deviceOrientation = myDevice.orientation;
BOOL isCurrentlyLandscapeView = UIDeviceOrientationIsLandscape(deviceOrientation);
[myDevice endGeneratingDeviceOrientationNotifications];

在我看来,这应该有效。我让设备接收设备方向通知,然后询问它的方向,但它不工作,我不知道为什么。

4

14 回答 14

120

真正的老线程,但没有真正的解决方案。

我有同样的问题,但发现获取 UIDeviceOrientation 并不总是一致的,所以改用这个:

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
于 2012-03-25T00:22:13.607 回答
76

如果 UIViewController:

if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
    // 
}

如果 UIView:

if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
    //
}

UIDevice.h:

#define UIDeviceOrientationIsPortrait(orientation)  ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown)
#define UIDeviceOrientationIsLandscape(orientation) ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight)

更新

将此代码添加到 xxx-Prefix.pch 然后您可以在任何地方使用它:

// 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

用法:

if (isLandscape) { NSLog(@"Landscape"); }
于 2012-12-12T09:49:51.613 回答
22

对于您首先要寻找的内容,如果方向改变,您必须获得通知!你可以在 viewDidLoad 中设置这个东西,比如

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

并且每当您的设备的方向发生变化时,都会调用OrientationDidChange,您可以根据方向做任何您想做的事情

-(void)OrientationDidChange:(NSNotification*)notification
{
    UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];

    if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight)
    {
    }
    else if(Orientation==UIDeviceOrientationPortrait)
    {
    }
}
于 2014-10-30T12:30:55.690 回答
22

如果您想直接从加速度计获取设备方向[[UIDevice currentDevice] orientation],请使用. 但是,如果您需要应用程序的当前方向(界面方向),请使用[[UIApplication sharedApplication] statusBarOrientation].

于 2015-01-07T22:56:15.627 回答
9

UIViewController有一个interfaceOrientation属性,你可以访问它来找出视图控制器的当前方向。

至于你的例子,那应该有效。当你说它不起作用时,你是什么意思?它给你的结果与你的预期相比是什么?

于 2011-04-05T23:15:25.573 回答
8

在 Swift 3.0 中

获取设备方向。

/* return current device orientation.
   This will return UIDeviceOrientationUnknown unless device orientation notifications are being generated. 
*/
UIDevice.current.orientation

从您的应用程序获取设备方向

UIApplication.shared.statusBarOrientation
于 2016-12-22T13:34:59.343 回答
4

对"UIDeviceOrientation"不满意,因为当 UIViewcontroller 方向固定到特定方向时,您不会获得与设备方向相关的信息,因此正确的做法是使用"UIInterfaceOrientation"

您可以使用"self.interfaceOrientation"从 UIViewController 获取方向,但是当您分解我们的代码时,您可能需要在视图控制器(自定义视图、类别...)之外进行这种测试,所以您仍然可以使用rootviewController访问控制器之外的任何地方的信息:

if (UIInterfaceOrientationIsLandscape(view.window.rootViewController.interfaceOrientation)) {
}
于 2013-07-12T08:06:44.913 回答
2

无论是否启用方向锁定,都有一种方法可以通过使用来自 CoreMotion 的数据来实现。这是代码:

#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");
                                }

                            }

}];
于 2015-08-24T03:23:32.897 回答
1

您是否为设备方向解锁了硬件锁?我的 iPad 1 边缘有一个。

于 2011-04-05T23:24:31.897 回答
1

这里有一些 Swift 变量可以让检测更容易:

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
于 2016-01-20T00:33:17.310 回答
0

使用此功能。

    func deviceOrientation() -> String! {
    let device = UIDevice.current
    if device.isGeneratingDeviceOrientationNotifications {
            device.beginGeneratingDeviceOrientationNotifications()
            var deviceOrientation: String
            let deviceOrientationRaw = device.orientation.rawValue
            switch deviceOrientationRaw {
            case 1:
                deviceOrientation = "Portrait"
            case 2:
                deviceOrientation = "Upside Down"
            case 3:
                deviceOrientation = "Landscape Right"
            case 4:
                deviceOrientation = "Landscape Left"
            case 5:
                deviceOrientation = "Camera Facing Down"
            case 6:
                deviceOrientation = "Camera Facing Up"
            default:
                deviceOrientation = "Unknown"
            }
            return deviceOrientation
        } else {
            return nil
        }
    }
于 2021-05-29T00:47:04.820 回答
0

我目前这样做的方式:

+ (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);
    }
}

如果由于某种原因没有 rootViewController 对 statusBarOrientation 不安全...

于 2019-07-18T01:32:58.963 回答
0

以及 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 }
}
于 2019-12-23T18:53:16.310 回答
0

这是我使用 Combine 的解决方案,它很容易与 SwiftUI 或常规 Swift 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
            ...
        }) 

于 2021-04-24T23:54:55.633 回答