在Swift中获取设备方向


78

我想知道如何在Swift中获得当前的设备方向?我知道有一些Objective-C的示例,但是我无法在Swift中运行它。

我正在尝试确定设备方向,并将其放入if语句中。

这是我遇到最多问题的那条线:

[[UIApplication sharedApplication] statusBarOrientation]

你有什么问题?将其转换为Swift还是获得您期望的值?
DavidRönnqvist2014年

1
设备方向不一定与您的UI方向匹配。外壳点-将设备放平并测试代码!
帕特里克

Answers:


70

您可以使用:

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    var text=""
    switch UIDevice.currentDevice().orientation{
    case .Portrait:
        text="Portrait"
    case .PortraitUpsideDown:
        text="PortraitUpsideDown"
    case .LandscapeLeft:
        text="LandscapeLeft"
    case .LandscapeRight:
        text="LandscapeRight"
    default:
        text="Another"
    }
    NSLog("You have moved: \(text)")        
}

SWIFT 3更新

override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
    var text=""
    switch UIDevice.current.orientation{
    case .portrait:
        text="Portrait"
    case .portraitUpsideDown:
        text="PortraitUpsideDown"
    case .landscapeLeft:
        text="LandscapeLeft"
    case .landscapeRight:
        text="LandscapeRight"
    default:
        text="Another"
    }
    NSLog("You have moved: \(text)")        
}

要么

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
}

使用Notification,您可以检查:IOS8 Swift:如何检测方向变化?

注意: 不推荐使用didRotateFromInterfaceOrientation,对于iOS 2.0和更高版本,请使用 viewWillTransitionToSize

如果是正面朝上和正面朝下,则将无法使用。因此,我们需要使用以下内容。

if UIApplication.shared.statusBarOrientation.isLandscape {
     // activate landscape changes
} else {
     // activate portrait changes
}

感谢您的分享!
ssowri1

嗯...如果用户已经旋转后导航到该视图,我们将不知道起始方向...
ScottyBlades

如果不推荐使用此功能,您仍然可以使用它。不要忘记在实现中将其称为超级方法。即:super.didRotate(from: fromInterfaceOrientation)。来自Apple文档:“此方法的实现必须在执行过程中的某个时刻调用super。”
博卡西卡

55

要像您拥有的Objective-C代码那样获得状态栏(以及UI)的方向,只需:

UIApplication.sharedApplication().statusBarOrientation

您还可以使用UIDevice的orientation属性

UIDevice.currentDevice().orientation

但是,这可能与您的UI所处的方向不符。从文档中:

该属性的值是一个常数,指示设备的当前方向。此值代表设备的物理方向,并且可能与应用程序用户界面的当前方向不同。有关可能值的说明,请参见“ UIDeviceOrientation”。


UIApplication.sharedApplication()。statusBarOrientation仅在主线程上
Yair hadad '18

谢谢您的帮助!
ssowri1

1
我正在使用uidevice.current.orientation.isportrait来检查设备方向并更改应用程序的ui,但即使将设备放在桌面上,它也在更改。但由于现在的工作perfactly精
格法姆·坎

迅速更新5.1-> UIDevice.current.orientation
罗纳尔多·阿尔贝蒂尼

如果设备方向是面朝上或面朝下,则UIDevice.current.orientation.isPortrait无效。检查状态栏(如此答案给出的)一直保持一致,并为我工作。
奥斯汀

26

苹果公司最近摆脱了“风景vs人像”的概念,更喜欢我们使用屏幕尺寸。但是,这可行:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.currentDevice().orientation.isLandscape.boolValue {
        print("landscape")
    } else {
        print("portrait")
    }
}

7
我会在您的解决方案中注意到苹果指出:“如果您在自定义视图控制器中覆盖此方法,则始终在实现的某个时刻调用super”
Popmedic

25
struct DeviceInfo {
struct Orientation {
    // indicate current device is in the LandScape orientation
    static var isLandscape: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isLandscape
                : UIApplication.shared.statusBarOrientation.isLandscape
        }
    }
    // indicate current device is in the Portrait orientation
    static var isPortrait: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isPortrait
                : UIApplication.shared.statusBarOrientation.isPortrait
        }
    }
}}

swift4回答:这就是我的方法,

1.适用于各种视图控制器

2.当用户旋转应用程序时也可以使用

3.也第一次安装该应用程序


1
完美的答案!谢谢
torap

很好,但是为什么要用拖曳时间代替@objc类呢?var isLandscape:Bool {return!isPortrait}我没有得到一些关键的东西吗?;)
Renetik

哇,它可以像我一样完美地工作。.非常感谢:)
Yogesh Patel

我怎么知道方向改变了?
Daniel Springer

14

斯威夫特4:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        if UIDevice.current.orientation.isLandscape {
            print("landscape")
        } else {
            print("portrait")
        }
    }

平面方向如何?
米哈尔Ziobro

1
不要忘记在覆盖函数的某个时刻调用super.viewWillTransition(to:size,with:coordinator)。
博卡西卡

13

要查找当前的设备方向,只需使用以下代码:

UIApplication.sharedApplication()。statusBarOrientation

快速3.0

UIApplication.shared.statusBarOrientation


iPad air 1&2返回的值不正确,iPad 2和iPhone是正确的。我真的是想找到一个适用于所有设备的设备,但是苹果在这里真是一团糟!:(
史蒂文·B。

与不同UIDevice.current.orientationUIApplication.shared.statusBarOrientation它在初始加载时可用,而不仅仅是在屏幕旋转后才可用。
ewizard

10

我在使用时遇到问题,InterfaceOrientation但它在加载时未访问方向,但工作正常。所以我尝试了这个,它是管理员。之所以可行,bounds.width是因为总是参考当前方向,而不是nativeBounds.width绝对方向。

    if UIScreen.mainScreen().bounds.height > UIScreen.mainScreen().bounds.width {
        // do your portrait stuff
    } else {    // in landscape
        // do your landscape stuff
    }

我称呼此为willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval)viewDidLoad但它很灵活。

感谢zSprawl提供该方向的指针。我应该指出,这仅对iOS 8及更高版本有用。


不适用于iOS 9和10 iPad,仅初始值正确,所有后续值均相反。
史蒂文·B。

@ Steven.B Hmmm ...在我的iPad Air,iPad 3和iOS 9下的模拟器上都可以正常工作。还可以与Beta测试人员一起使用。也许您还在使用其他影响此功能的代码。
bpedit

这段代码可能仅在UIViewcontroller中使用时才有效,我试图在自定义UIView类中获取方向和界限,但是当方向比框架正确或界限仍然错误时,我测试的几乎所有设备都会返回不同的值。
史蒂文·B。

10

因此,如果Apple不赞成使用整个方向字符串(“纵向”,“横向”),那么您所关心的只是宽高比。(有点像@bpedit的答案)

用宽度除以高度时,如果结果小于1,则mainScreen或容器或“纵向”“模式”中的任何内容。如果结果大于1,则为“风景”绘画。;)

override func viewWillAppear(animated: Bool) {
    let size: CGSize = UIScreen.mainScreen().bounds.size
    if size.width / size.height > 1 {
        print("landscape")
    } else {
        print("portrait")
    }
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if size.width / size.height > 1 {
        print("landscape")
    } else {
        print("portrait")
    }
}

(我猜想,如果您使用这种方法,那么当比率恰好为1,即宽度和高度相等时,您可能根本就不关心具体处理条件。)


1
真好!对您的答案的细微改进:不要忘记调用,super.viewWillAppear(animated)并且super.viewWillTransition(to: size, with: coordinator)在某些时候使用了覆盖函数
Bocaxica

8

迅捷3+

基本上:

NotificationCenter.default.addObserver(self, selector: #selector(self.didOrientationChange(_:)), name: .UIDeviceOrientationDidChange, object: nil)

@objc func didOrientationChange(_ notification: Notification) {
    //const_pickerBottom.constant = 394
    print("other")
    switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("portrait")
        default:
            print("other")
    }
}

:)


我喜欢这个答案。对于无法使用的较大屏幕(如iPad)非常有用,func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)因为traitcollection始终为width.regularand height.regular,因此traitCollection不会在旋转时发生变化。在Swift 4中,通知已重命名为UIDevice.orientationDidChangeNotification
博卡西卡

3

Swift 3,基于Rob的回答

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if (size.width / size.height > 1) {
        print("landscape")
    } else {
        print("portrait")
    }
}

2
不要忘记super.viewWillTransition(to: size, with: coordinator)在您的覆盖函数中的某个时刻调用
Bocaxica,

3

我发现Swift中的Obj-C代码的替代代码

if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) 

if UIApplication.shared.statusBarOrientation.isLandscape

注意:我们正在尝试查找状态栏方向是否为横向。如果是横向,则if语句为true。


2
   override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    if (toInterfaceOrientation.isLandscape) {
        NSLog("Landscape");
    }
    else {
        NSLog("Portrait");
    }
}

2

statusBarOrientation弃用,因此没有提供在使用像上述的答案

在此代码中,无需担心折旧即可获得方向。Swift 5 ioS 13.2已测试100%

struct Orientation {
    // indicate current device is in the LandScape orientation
    static var isLandscape: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isLandscape
                : (UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isLandscape)!
        }
    }
    // indicate current device is in the Portrait orientation
    static var isPortrait: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isPortrait
                : (UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isPortrait)!
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.