yattee/iOS/OrientationTracker.swift
Toni Förster 94577332a1
chore: address linter warnings
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
2024-08-18 14:46:51 +02:00

99 lines
3.1 KiB
Swift

import CoreMotion
import UIKit
public class OrientationTracker {
public static let shared = OrientationTracker()
public static let deviceOrientationChangedNotification = NSNotification.Name("DeviceOrientationChangedNotification")
public var currentDeviceOrientation: UIDeviceOrientation = .portrait
public var currentInterfaceOrientation: UIInterfaceOrientation {
switch currentDeviceOrientation {
case .landscapeLeft:
return .landscapeLeft
case .landscapeRight:
return .landscapeRight
default:
return .portrait
}
}
public var currentInterfaceOrientationMask: UIInterfaceOrientationMask {
switch currentInterfaceOrientation {
case .landscapeLeft:
return .landscapeLeft
case .landscapeRight:
return .landscapeRight
default:
return .portrait
}
}
public var affineTransform: CGAffineTransform {
var angleRadians: Double
switch currentDeviceOrientation {
case .portrait:
angleRadians = 0
case .landscapeLeft:
angleRadians = -0.5 * .pi
case .landscapeRight:
angleRadians = 0.5 * .pi
case .portraitUpsideDown:
angleRadians = .pi
default:
return .identity
}
return CGAffineTransform(rotationAngle: angleRadians)
}
private let motionManager: CMMotionManager
private let queue: OperationQueue
private init() {
motionManager = CMMotionManager()
motionManager.accelerometerUpdateInterval = 0.1
queue = OperationQueue()
}
public func startDeviceOrientationTracking() {
motionManager.startAccelerometerUpdates(to: queue) { accelerometerData, error in
guard error == nil else { return }
guard let accelerometerData else { return }
let newDeviceOrientation = self.deviceOrientation(forAccelerometerData: accelerometerData)
guard newDeviceOrientation != self.currentDeviceOrientation else { return }
self.currentDeviceOrientation = newDeviceOrientation
NotificationCenter.default.post(
name: Self.deviceOrientationChangedNotification,
object: nil,
userInfo: nil
)
}
}
public func stopDeviceOrientationTracking() {
motionManager.stopAccelerometerUpdates()
}
private func deviceOrientation(forAccelerometerData accelerometerData: CMAccelerometerData) -> UIDeviceOrientation {
let threshold = 0.55
if accelerometerData.acceleration.x >= threshold {
return .landscapeLeft
}
if accelerometerData.acceleration.x <= -threshold {
return .landscapeRight
}
if accelerometerData.acceleration.y <= -threshold {
return .portrait
}
if UIDevice.current.userInterfaceIdiom == .pad && accelerometerData.acceleration.y >= threshold {
return .portraitUpsideDown
}
return currentDeviceOrientation
}
}