即使设备的方向已锁定,也可获取当前的iOS设备方向

时间:2018-03-08 02:15:58

标签: ios swift core-motion

即使设备的方向被锁定,我也希望获得当前的iOS设备方向。 (就像iOS相机应用程序一样)

我想至少检测人像,风景左和风景右。

当方向被锁定时,UIDeviceOrientation和UIInterfaceOrientation似乎不起作用。

在这种情况下,我认为我们将使用CoreMotion。

如何在swift4中对其进行逻辑处理?

3 个答案:

答案 0 :(得分:10)

使用核心动作声明动作管理

    var orientationLast = UIInterfaceOrientation(rawValue: 0)!
    var motionManager: CMMotionManager?

动作管理器初始化

并在viewDidLoad中调用此函数

    func initializeMotionManager() {
     motionManager = CMMotionManager()
     motionManager?.accelerometerUpdateInterval = 0.2
     motionManager?.gyroUpdateInterval = 0.2
     motionManager?.startAccelerometerUpdates(to: (OperationQueue.current)!, withHandler: {
        (accelerometerData, error) -> Void in
        if error == nil {
            self.outputAccelertionData((accelerometerData?.acceleration)!)
        }
        else {
            print("\(error!)")
        }
        })
     }   

分析加速度计仪表数据

 func outputAccelertionData(_ acceleration: CMAcceleration) {
    var orientationNew: UIInterfaceOrientation
    if acceleration.x >= 0.75 {
        orientationNew = .landscapeLeft
        print("landscapeLeft")
    }
    else if acceleration.x <= -0.75 {
        orientationNew = .landscapeRight
        print("landscapeRight")
    }
    else if acceleration.y <= -0.75 {
        orientationNew = .portrait
        print("portrait")

    }
    else if acceleration.y >= 0.75 {
        orientationNew = .portraitUpsideDown
        print("portraitUpsideDown")
    }
    else {
        // Consider same as last time
        return
    }

    if orientationNew == orientationLast {
        return
    }
    orientationLast = orientationNew
}

答案 1 :(得分:0)

快速5

声明

var motionManager   : CMMotionManager!

初始化

func addCoreMotion() {

    let splitAngle:Double = 0.75
    let updateTimer:TimeInterval = 0.5

    motionManager = CMMotionManager()
    motionManager?.gyroUpdateInterval = updateTimer
    motionManager?.accelerometerUpdateInterval = updateTimer

    var orientationLast    = UIInterfaceOrientation(rawValue: 0)!

    motionManager?.startAccelerometerUpdates(to: (OperationQueue.current)!, withHandler: {
        (acceleroMeterData, error) -> Void in
        if error == nil {

            let acceleration = (acceleroMeterData?.acceleration)!
            var orientationNew = UIInterfaceOrientation(rawValue: 0)!

            if acceleration.x >= splitAngle {
                orientationNew = .landscapeLeft
            }
            else if acceleration.x <= -(splitAngle) {
                orientationNew = .landscapeRight
            }
            else if acceleration.y <= -(splitAngle) {
                orientationNew = .portrait
            }
            else if acceleration.y >= splitAngle {
                orientationNew = .portraitUpsideDown
            }

            if orientationNew != orientationLast && orientationNew != .unknown{
                orientationLast = orientationNew
                self.deviceOrientationChanged(orinetation: orientationNew)
            }
        }
        else {
            print("error : \(error!)")
        }
    })
}

结果

 func deviceOrientationChanged(orinetation:UIInterfaceOrientation) {

      print("orinetation :",orinetation.rawValue)
     // updatYourUI or another stuff

 }

答案 2 :(得分:0)

这里是检测设备旋转并返回UIDeviceOrientation的示例。 此解决方案使用CoreMotion并在所有情况下均适用。

示例

let orientationManager = APOrientationManager()
orientationManager.delegate = self
/// start detect rotation
orientationManager.startMeasuring()

/// get current interface orientation
let orientation = orientationManager.currentInterfaceOrientation()
print(orientation.rawValue)

/// stop detect rotation
orientationManager.stopMeasuring()
orientationManager.delegate = nil

遵守委托人

extension ViewController: APOrientationManagerDelegate {
    func didChange(deviceOrientation: UIDeviceOrientation) {
        /// update UI in main thread
    }
}

APOrientationManager.swift

import Foundation
import CoreMotion
import AVFoundation

protocol APOrientationManagerDelegate: class {
    func didChange(deviceOrientation: UIDeviceOrientation)
}

class APOrientationManager {

    private let motionManager = CMMotionManager()
    private let queue = OperationQueue()
    private var deviceOrientation: UIDeviceOrientation = .unknown
    weak var delegate: APOrientationManagerDelegate?

    init() {
        motionManager.accelerometerUpdateInterval = 1.0
        motionManager.deviceMotionUpdateInterval = 1.0
        motionManager.gyroUpdateInterval = 1.0
        motionManager.magnetometerUpdateInterval = 1.0
    }

    func startMeasuring() {
        guard motionManager.isDeviceMotionAvailable else {
            return
        }
        motionManager.startAccelerometerUpdates(to: queue) { [weak self] (accelerometerData, error) in
            guard let strongSelf = self else {
                return
            }
            guard let accelerometerData = accelerometerData else {
                return
            }

            let acceleration = accelerometerData.acceleration
            let xx = -acceleration.x
            let yy = acceleration.y
            let z = acceleration.z
            let angle = atan2(yy, xx)
            var deviceOrientation = strongSelf.deviceOrientation
            let absoluteZ = fabs(z)

            if deviceOrientation == .faceUp || deviceOrientation == .faceDown {
                if absoluteZ < 0.845 {
                    if angle < -2.6 {
                        deviceOrientation = .landscapeRight
                    } else if angle > -2.05 && angle < -1.1 {
                        deviceOrientation = .portrait
                    } else if angle > -0.48 && angle < 0.48 {
                        deviceOrientation = .landscapeLeft
                    } else if angle > 1.08 && angle < 2.08 {
                        deviceOrientation = .portraitUpsideDown
                    }
                } else if z < 0 {
                    deviceOrientation = .faceUp
                } else if z > 0 {
                    deviceOrientation = .faceDown
                }
            } else {
                if z > 0.875 {
                    deviceOrientation = .faceDown
                } else if z < -0.875 {
                    deviceOrientation = .faceUp
                } else {
                    switch deviceOrientation {
                    case .landscapeLeft:
                        if angle < -1.07 {
                            deviceOrientation = .portrait
                        }
                        if angle > 1.08 {
                            deviceOrientation = .portraitUpsideDown
                        }
                    case .landscapeRight:
                        if angle < 0 && angle > -2.05 {
                            deviceOrientation = .portrait
                        }
                        if angle > 0 && angle < 2.05 {
                            deviceOrientation = .portraitUpsideDown
                        }
                    case .portraitUpsideDown:
                        if angle > 2.66 {
                            deviceOrientation = .landscapeRight
                        }
                        if angle < 0.48 {
                            deviceOrientation = .landscapeLeft
                        }
                    case .portrait:
                        if angle > -0.47 {
                            deviceOrientation = .landscapeLeft
                        }
                        if angle < -2.64 {
                            deviceOrientation = .landscapeRight
                        }
                    default:
                        if angle > -0.47 {
                            deviceOrientation = .landscapeLeft
                        }
                        if angle < -2.64 {
                            deviceOrientation = .landscapeRight
                        }
                    }
                }
            }
            if strongSelf.deviceOrientation != deviceOrientation {
                strongSelf.deviceOrientation = deviceOrientation
                strongSelf.delegate?.didChange(deviceOrientation: deviceOrientation)
            }
        }
    }

    func stopMeasuring() {
        motionManager.stopAccelerometerUpdates()
    }

    func currentInterfaceOrientation() -> AVCaptureVideoOrientation {
        switch deviceOrientation {
        case .portrait:
            return .portrait
        case .landscapeRight:
            return .landscapeLeft
        case .landscapeLeft:
            return .landscapeRight
        case .portraitUpsideDown:
            return .portraitUpsideDown
        default:
            return .portrait
        }
    }
}