Getting the orientation of the camera relative to the user interface

Apple in all their wisdom has deprecated almost every API that can be used to get the interface orientation because they want developers to treat an orientation change as a simple size change.

However, there are other uses for the interface orientation other than adjusting the UI. Since the camera is fixed to the device, and does not rotate with the interface, images from the camera need to be adjusted for orientation when displaying and/or processing them for computer vision tasks. Using traits is not a reliable way of determining the orientation, especially when running on an iPad.

What is the recommended way to determine the relative angle of the camera in relation to the interface now all the interfaceOrientation APIs are deprecated? And specifically: how to get a notification of an interface orientation change?

Replies

Here is a general approach using Core Motion to determine device orientation and receive notifications for orientation changes:

Core Motion Framework: Use the Core Motion framework to access motion data from the device. You can obtain information about the device's attitude, which includes the pitch, roll, and yaw angles.

CMMotionManager: Create an instance of CMMotionManager to start receiving motion updates. The deviceMotion property provides access to the CMDeviceMotion object, which contains attitude information.

Notification for Orientation Change: To receive notifications when the device orientation changes, you can observe changes in the attitude information, specifically the pitch, roll, and yaw angles.

Here's a simplified example in Swift:


class OrientationManager {
    let motionManager = CMMotionManager()

    init() {
        if motionManager.isDeviceMotionAvailable {
            motionManager.deviceMotionUpdateInterval = 0.1  // Set the desired update interval

            // Start device motion updates
            motionManager.startDeviceMotionUpdates(to: .main) { [weak self] (motion, error) in
                guard let motion = motion else {
                    return
                }

                // Extract pitch, roll, and yaw angles from motion data
                let pitch = motion.attitude.pitch
                let roll = motion.attitude.roll
                let yaw = motion.attitude.yaw

                // Handle orientation changes here
                // You may compare these angles to determine orientation

                // Example: Detect a change in pitch angle
                if abs(pitch) > 1.0 {
                    print("Device orientation changed!")
                }
            }
        }
    }
}

Remember to stop motion updates when they are no longer needed to conserve battery life:

Please check the latest Apple documentation for any updates or changes in the recommended approach, as APIs and best practices can evolve over time. Additionally, consider exploring the Vision framework for computer vision tasks, as it may offer improved support for handling device orientation-related issues in more recent iOS versions.

  • I'm looking for changes in interface orientation, which is not the same as the device orientation. (e.g. if you have rotation lock enabled the device orientation can change without changing the interface orientation. There are also a few device orientations that do not affect the interface orientation even if it's unlocked, such as .faceUp and .faceDown.

Add a Comment

I believe what you are looking for is https://developer.apple.com/documentation/avfoundation/avcapturedevicerotationcoordinator

  • This is exactly what I'm looking for, unfortunately it's only available on iOS 17. I need to support iOS 14 and later.

Add a Comment