即使设备的方向被锁定,我也希望获得当前的iOS设备方向。 (就像iOS相机应用程序一样)
我想至少检测人像,风景左和风景右。
当方向被锁定时,UIDeviceOrientation和UIInterfaceOrientation似乎不起作用。
在这种情况下,我认为我们将使用CoreMotion。
如何在swift4中对其进行逻辑处理?
答案 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
}
}
}