SwiftUI : AVCaptureVideoPreviewLayer orientation in iOS 17

217 Views Asked by At

I'm newish to mobile development in SwiftUI and have spun my wheels on this for quite awhile now. I have looked at the official documentation, but remain confused. My preview layer is not correctly handling camera orientation meaning that although the phone is in landscape mode the orientation will only update to 90 degrees. I have included Supported Interface orientations in my info.plist and settings are not restrictive to rotation angle. Here is snip it of my class. Thank you for the help.

class CameraView: UIViewController, AVCapturePhotoCaptureDelegate {
    var currentVideoRotationAngle: CGFloat = 0

    func capturePhoto(completion: @escaping (UIImage?) -> Void) {
        print("capturePhoto method called")

        sessionQueue.async {
            guard self.captureSession.isRunning else {
                print("Capture session is not running")
                completion(nil)
                return
            }

            DispatchQueue.main.async {
                self.updateVideoOrientation()
                print("Video orientation updated to: \(self.currentVideoRotationAngle) degrees")

                let settings = AVCapturePhotoSettings()
                if let connection = self.photoOutput.connection(with: .video) {
                    connection.videoRotationAngle = self.currentVideoRotationAngle
                    print("Photo output connection video rotation angle set to: \(self.currentVideoRotationAngle) degrees")
                }

                self.photoOutput.capturePhoto(with: settings, delegate: self)
                print("Photo capture initiated with settings")
            }
        }

        self.photoCaptureCompletion = completion
        print("Photo capture completion handler set")
    }

    private let photoOutput = AVCapturePhotoOutput()
    var photoCaptureCompletion: ((UIImage?) -> Void)?

    
    override func viewDidLoad() {
        super.viewDidLoad()
        print("ViewDidLoad: Camera View")
        checkPermission()
        setupCaptureSession()
        
        // Subscribe to orientation change notifications
           NotificationCenter.default.addObserver(self, selector: #selector(orientationDidChange), name: UIDevice.orientationDidChangeNotification, object: nil)
           UIDevice.current.beginGeneratingDeviceOrientationNotifications()
    }
    
    @objc func orientationDidChange() {
        print("OrientationDidChange method called")
        let currentOrientation = currentVideoRotationAngle
        print("Orientation changed: \(currentOrientation)")
    }

    private func updateVideoOrientation() {
        
        let orientation = UIDevice.current.orientation
        
        switch orientation {
        case UIDeviceOrientation.portraitUpsideDown:
            print("Orientation: Portrait Upside Down")
            currentVideoRotationAngle = 270
            
            // Home button on right
        case UIDeviceOrientation.landscapeLeft:
            print("Orientation: Landscape Right")
            currentVideoRotationAngle = 0
            
            // Home button on left
        case UIDeviceOrientation.landscapeRight:
            print("Orientation: Landscape Left")
            currentVideoRotationAngle = 180
            
            // Home button at bottom
        case UIDeviceOrientation.portrait:
            print("Orientation: Portrait")
            currentVideoRotationAngle = 90
        default:
            break
        }
        
        self.previewLayer.connection?.videoRotationAngle = currentVideoRotationAngle
    }
0

There are 0 best solutions below