Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum conversion of UIInterfaceOrientation to AVCaptureVideoOrientation in Swift

Tags:

ios

swift

I'm playing around with using AVFoundation in Swift

Normally when I set up a video camera capture session I do something like the following in objective-c

[[cameraView.previewLayer connection] setVideoOrientation:(AVCaptureVideoOrientation)[self interfaceOrientation]]

In swift it seems like I have to do something like this (because of optional type)

if let connection = cameraView.previewLayer?.connection {
  connection.videoOrientation = self.interfaceOrientation as AVCaptureVideoOrientation
}

however this complains with

‘AVCaptureVideoOrientation’ is not a subtype of ‘UIInterfaceOrientation’

After reading about the down-casting methodology this makes a lot of sense, but I'm struggling to find how to actually get this working.

Do I need to write a helper method that basically does a switch statement through all the available values of UIInterfaceOrientation to get this working?

like image 330
PolandSpring Avatar asked Jun 08 '14 20:06

PolandSpring


3 Answers

swift 3

extension UIDeviceOrientation {
    var videoOrientation: AVCaptureVideoOrientation? {
        // Unlike UIInterfaceOrientation, the UIDeviceOrientation has reversed landscape left/right. Doh!
        switch self {
        case .portraitUpsideDown: return .portraitUpsideDown
        case .landscapeRight: return .landscapeLeft
        case .landscapeLeft: return .landscapeRight
        case .portrait: return .portrait
        default: return nil
        }
    }
}

extension UIInterfaceOrientation {
    var videoOrientation: AVCaptureVideoOrientation? {
        switch self {
        case .portraitUpsideDown: return .portraitUpsideDown
        case .landscapeRight: return .landscapeRight
        case .landscapeLeft: return .landscapeLeft
        case .portrait: return .portrait
        default: return nil
        }
    }
}
like image 181
neoneye Avatar answered Nov 17 '22 19:11

neoneye


Thanks, David. I updated to Swift 3 and added UIDeviceOrientation:

extension AVCaptureVideoOrientation {
    var uiInterfaceOrientation: UIInterfaceOrientation {
        get {
            switch self {
            case .landscapeLeft:        return .landscapeLeft
            case .landscapeRight:       return .landscapeRight
            case .portrait:             return .portrait
            case .portraitUpsideDown:   return .portraitUpsideDown
            }
        }
    }

    init(ui:UIInterfaceOrientation) {
        switch ui {
        case .landscapeRight:       self = .landscapeRight
        case .landscapeLeft:        self = .landscapeLeft
        case .portrait:             self = .portrait
        case .portraitUpsideDown:   self = .portraitUpsideDown
        default:                    self = .portrait
        }
    }

    init?(orientation:UIDeviceOrientation) {
        switch orientation {
        case .landscapeRight:       self = .landscapeLeft
        case .landscapeLeft:        self = .landscapeRight
        case .portrait:             self = .portrait
        case .portraitUpsideDown:   self = .portraitUpsideDown
        default:
            return nil
        }
    }
}

Then I use it with AVCapturePhotoOutput like this:

if let connection = imageOutput.connection(withMediaType: AVMediaTypeVideo),
    connection.isVideoOrientationSupported,
    let orientation = AVCaptureVideoOrientation(orientation: UIDevice.current.orientation) {
    connection.videoOrientation = orientation
}

It may not be perfect for every scenario but since my interface doesn't change with orientation I skip listening for orientation changes.

It's probably better in general to change your UI so users have an idea of what orientation they're using.

like image 44
garafajon Avatar answered Nov 17 '22 19:11

garafajon


As I noted in my comments, since AVCaptureVideoOrientation and UIInterfaceOrientation don't match up their cases, you can use something like:

extension AVCaptureVideoOrientation {
    var uiInterfaceOrientation: UIInterfaceOrientation {
        get {
            switch self {
            case .LandscapeLeft:        return .LandscapeLeft
            case .LandscapeRight:       return .LandscapeRight
            case .Portrait:             return .Portrait
            case .PortraitUpsideDown:   return .PortraitUpsideDown
            }
        }
    }

    init(ui:UIInterfaceOrientation) {
        switch ui {
        case .LandscapeRight:       self = .LandscapeRight
        case .LandscapeLeft:        self = .LandscapeLeft
        case .Portrait:             self = .Portrait
        case .PortraitUpsideDown:   self = .PortraitUpsideDown
        default:                    self = .Portrait
        }
    }
}

then use it as:

if let connection = cameraView.previewLayer?.connection {
    connection.videoOrientation = AVCaptureVideoOrientation(ui:self.interfaceOrientation)
}
like image 27
David Berry Avatar answered Nov 17 '22 19:11

David Berry