Enum конвертация UIInterfaceOrientation в AVCaptureVideoOrientation в Swift

Я играю с использованием AVFoundation в Swift

Обычно, когда я настраиваю сеанс захвата видеокамеры, я делаю что-то вроде следующего в objective-c

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

В быстром мне кажется, что я должен сделать что-то вроде этого (из-за необязательного типа)

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

однако это жалуется на

‘AVCaptureVideoOrientation’ is not a subtype of ‘UIInterfaceOrientation’

После прочтения методологии down-casting это имеет большой смысл, но я изо всех сил пытаюсь найти, как на самом деле получить эту работу.

Мне нужно написать вспомогательный метод, который в основном выполняет оператор switch через все доступные значения UIInterfaceOrientation, чтобы заставить это работать?

Ответ 1

Как я уже отмечал в своих комментариях, поскольку AVCaptureVideoOrientation и UIInterfaceOrientation не соответствуют их случаям, вы можете использовать что-то вроде:

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
        }
    }
}

то используйте его как:

if let connection = cameraView.previewLayer?.connection {
    connection.videoOrientation = AVCaptureVideoOrientation(ui:self.interfaceOrientation)
}

Ответ 2

Спасибо, Дэвид. Я обновился до Swift 3 и добавил 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
        }
    }
}

Затем я использую его с AVCapturePhotoOutput следующим образом:

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

Это может быть не идеально для каждого сценария, но поскольку мой интерфейс не меняется с ориентацией, я пропускаю прослушивание изменений ориентации.

Вероятно, лучше вообще изменить свой пользовательский интерфейс, чтобы пользователи имели представление о том, какую ориентацию они используют.

Ответ 3

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
        }
    }
}

Ответ 4

Добавлено через 10 минут.

Выяснилось, если вы споткнулись об этом, сделав что-то вроде

connection.videoOrientation = AVCaptureVideoOrientation.fromRaw(self.interfaceOrientation.toRaw())!

похоже, работает.