在Swift中,如何在设备启动后正确获得设备方向?

时间:2015-12-24 12:13:28

标签: ios swift swift2 orientation uiinterfaceorientation

我使用以下代码查看设备是否处于横向模式:

UIDevice.currentDevice().orientation.isLandscape.boolValue

如果我在启动应用程序之前将设备置于横向模式,并且在viewDidLoad之后,我调用这行代码,它总是会返回false

如果我改用它:

interfaceOrientation.isLandscape

它返回true,这是正确的,但编译器显示警告interfaceOrientation was deprecated in iOS 8.0

在应用启动后立即获取设备方向的正确方法是什么?

5 个答案:

答案 0 :(得分:6)

DeviceOrientation vs. ScreenSize vs StatusBar.isLandscape?

iOS 11,Swift 4和Xcode 9.X

无论是否使用AutoLayout,有几种方法可以获得正确的设备方向,它们可以用于在使用应用程序时检测旋转变化,以及在应用程序启动时或从背景恢复后获得正确的方向

此解决方案在iOS 11和Xcode 9.X中运行良好

<强> 1。 UIScreen.main.bounds.size: 如果您只想知道该应用是处于横向模式还是纵向模式,那么最佳起点是viewDidLoad在发布时的rootViewControllerviewWillTransition(toSize:)中的rootViewController如果你想在应用程序处于后台时检测旋转变化,并且应该以正确的方向恢复UI。

let size = UIScreen.main.bounds.size
if size.width < size.height {
    print("Portrait: \(size.width) X \(size.height)")
} else {
    print("Landscape: \(size.width) X \(size.height)")
}

这也发生在app / viewController生命周期的早期。

<强> 2。通知中心

如果您需要获取实际的设备方向(包括faceDown,faceUp等)。您想按如下方式添加观察者(即使您在application:didFinishLaunchingWithOptions中的AppDelegate方法中执行此操作,第一次通知可能会在执行viewDidLoad后触发

device = UIDevice.current
device?.beginGeneratingDeviceOrientationNotifications()
notificationCenter = NotificationCenter.default
notificationCenter?.addObserver(self, selector: #selector(deviceOrientationChanged),
    name: Notification.Name("UIDeviceOrientationDidChangeNotification"),
    object: nil)

按如下方式添加选择器。我将其拆分为两部分,以便能够在inspectDeviceOrientation()

中运行viewWillTransition
@objc func deviceOrientationChanged() {
    print("Orientation changed")
    inspectDeviceOrientation()
}

func inspectDeviceOrientation() {
    let orientation = UIDevice.current.orientation
    switch UIDevice.current.orientation {
    case .portrait:
        print("portrait")
    case .landscapeLeft:
        print("landscapeLeft")
    case .landscapeRight:
        print("landscapeRight")
    case .portraitUpsideDown:
        print("portraitUpsideDown")
    case .faceUp:
        print("faceUp")
    case .faceDown:
        print("faceDown")
    default: // .unknown
        print("unknown")
    }
    if orientation.isPortrait { print("isPortrait") }
    if orientation.isLandscape { print("isLandscape") }
    if orientation.isFlat { print("isFlat") }
}

请注意,UIDeviceOrientationDidChangeNotification可能会在发布期间多次发布,在某些情况下可能会.unknown。我看到的是,在viewDidLoadviewWillAppear方法之后,viewDidAppear之前,甚至applicationDidBecomeActive

之前收到了第一个正确的方向通知

方向对象将为您提供所有7种可能的方案(来自enum UIDeviceOrientation定义):

public enum UIDeviceOrientation : Int {
    case unknown
    case portrait // Device oriented vertically, home button on the bottom
    case portraitUpsideDown // Device oriented vertically, home button on the top
    case landscapeLeft // Device oriented horizontally, home button on the right
    case landscapeRight // Device oriented horizontally, home button on the left
    case faceUp // Device oriented flat, face up
    case faceDown // Device oriented flat, face down
}

有趣的是,isPortrait只读Bool变量在UIDeviceOrientation的扩展名中定义如下:

extension UIDeviceOrientation {
    public var isLandscape: Bool { get }
    public var isPortrait: Bool { get }
    public var isFlat: Bool { get }
    public var isValidInterfaceOrientation: Bool { get }
}

第3。 StatusBarOrientation

UIApplication.shared.statusBarOrientation.isLandscape 

这也适用于确定方向是纵向还是横向,并提供与第1点相同的结果。您可以在viewDidLoad(适用于应用启动)和viewWillTransition(toSize:)中进行评估,如果来自背景。但它不会通过通知(第2点)向您提供上/下,左/右,上/下的详细信息

答案 1 :(得分:1)

在检查方向isValidInterfaceOrientation之前应检测到isLandscape不要用 isValidInterfaceOrientation == false处理文本消息(当它的值为isLandscape时)。

在对此进行更仔细的阅读之前,我对此感到不知所措。考虑到isValidInterfaceOrientation,效果很好。

@objc func rotated() {
    if (UIDevice.current.orientation.isValidInterfaceOrientation) {
        if (UIDevice.current.orientation.isLandscape) { 
            if(!bLandscape) {
                bLandscape = true
                setupTabBar() // Repaint the app
            }
        } else { // Portait 
            if(bLandscape) {
                bLandscape = false
                setupTabBar() // Repaint the app 
            }
        }
    }
}

答案 2 :(得分:0)

我已多次测试过方向,所以我总结了一些经验。

在除iPhone6之外的所有iPhone设备中,唯一的界面方向是.portrait。如果App以横向模式启动,则必须更改方向。一个人将收到UIDeviceOrientationDidChangeNotification。现在是获得指导的合适时间。

关于使用iPhone6进行横向启动时,启动后的方向将改变一次: enter image description here

使用iPhone6 plus进行横向启动时,启动后方向永远不会改变: enter image description here

使用相同应用的两个不同屏幕截图enter image description here

因此,在应用更改方向之前,方向仍然与主页中的方向相同。

viewDidLoad中,方向尚未更改,日志将是错误的方向。

答案 3 :(得分:0)

我在检测isFlat之前哪个方向时遇到问题,因此我将其放入视图控制器中

let orientation = UIDevice.current.orientation

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if  orientation.isPortrait {
        return .portrait
    } else if orientation.isFlat{
        if UIScreen.main.bounds.width < UIScreen.main.bounds.height{
            return .portrait
        } else {
            return .landscape
        }
    } else {
        return .landscape
    }
}

答案 4 :(得分:0)

这对我有用:

if UIScreen.main.bounds.width > UIScreen.main.bounds.height{
    print("Portraitmode!")
}

它可以根据显示尺寸在所有设备上使用: https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html