Skip to content

Instantly share code, notes, and snippets.

@darrarski
Created August 23, 2021 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrarski/32621c1499826f857dbd669c43506e19 to your computer and use it in GitHub Desktop.
Save darrarski/32621c1499826f857dbd669c43506e19 to your computer and use it in GitHub Desktop.
SwiftUI CoreMotion driven DeviceOrientationObserver
import CoreMotion
import SwiftUI
public final class DeviceOrientationObserver: ObservableObject {
public init() {
manager.startAccelerometerUpdates(to: OperationQueue.main) { [weak self] data, error in
guard error == nil, let acceleration = data?.acceleration else {
self?.value = .unknown
return
}
self?.value = deviceOrientation(from: acceleration)
}
}
@Published public var value: UIDeviceOrientation = .unknown
deinit {
manager.stopAccelerometerUpdates()
}
let manager = CMMotionManager()
}
private func deviceOrientation(from acceleration: CMAcceleration) -> UIDeviceOrientation {
let z = acceleration.z
if z <= -0.95 { return .faceUp }
if z >= 0.95 { return .faceDown }
switch atan2(acceleration.y, -acceleration.x) {
case -2.25 ... -0.75: return .portrait
case -0.75 ... 0.75: return .landscapeRight
case 0.75 ... 2.25: return .portraitUpsideDown
default: return .landscapeLeft
}
}
// MARK: - Example
struct ExampleView: View {
@StateObject var observer = DeviceOrientationObserver()
var body: some View {
Text("Device orientation: \(observer.value.title)")
}
}
extension UIDeviceOrientation {
var title: String {
switch self {
case .unknown: return "unknown"
case .portrait: return "portrait"
case .portraitUpsideDown: return "portraitUpsideDown"
case .landscapeLeft: return "landscapeLeft"
case .landscapeRight: return "landscapeRight"
case .faceUp: return "faceUp"
case .faceDown: return "faceDown"
@unknown default: return "unknown default"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment