Swift - 从主线程访问 UIApplication.shared.statusBarOrientation

Swift -access UIApplication.shared.statusBarOrientation from main thread

我正在尝试访问 UIApplication.shared.statusBarOrientation 但我一直收到错误 UIApplication.statusBarOrientation() must be used from main thread only:

我试图将它和使用它的 switch 语句添加到 mainQueue 中,但这导致 return value 从它包含的函数崩溃到 nil 值:

DispatchQueue.main.async {

    let interfaceOrientation = UIApplication.shared.statusBarOrientation

    switch interfaceOrientation {

    case .portrait, .portraitUpsideDown, .unknown:
        videoOrientation = .portrait
    case .landscapeLeft:
        videoOrientation = .landscapeRight
    case .landscapeRight:
        videoOrientation = .landscapeLeft
    @unknown default:
        break
    }
}

代码:

func videoOrientation() -> AVCaptureVideoOrientation {

    var videoOrientation: AVCaptureVideoOrientation!

    let orientation: UIDeviceOrientation = UIDevice.current.orientation

    switch orientation {

    case .faceUp, .faceDown, .unknown:

        // ** I tried to add this alone to the mainQueue but the switch statement couldn't access it so then I tried to add the entire switch but that lead to the return value crashing with a nil
        let interfaceOrientation = UIApplication.shared.statusBarOrientation

        switch interfaceOrientation {

        case .portrait, .portraitUpsideDown, .unknown:
            videoOrientation = .portrait
        case .landscapeLeft:
            videoOrientation = .landscapeRight
        case .landscapeRight:
            videoOrientation = .landscapeLeft
        @unknown default:
            break
        }

    case .portrait, .portraitUpsideDown:
        videoOrientation = .portrait
    case .landscapeLeft:
        videoOrientation = .landscapeRight
    case .landscapeRight:
        videoOrientation = .landscapeLeft
    @unknown default:
        break
    }

    return videoOrientation // ** crashes here **
}

我在按下 camerButton 以使用 AVFoundation 录制视频时访问 return 值。 movieFileOutput 对象在此行访问 videoOrientation movieFileOutput.connection(with: AVMediaType.video)?.videoOrientation = videoOrientation():

代码:

let captureSession = AVCaptureSession()
var movieFileOutput = AVCaptureMovieFileOutput()
var videoFileUrlFromCamera: URL?

func startRecording() {

    if !captureSession.outputs.contains(movieFileOutput) {
        return
    }

    // Stop recording
    if movieFileOutput.isRecording {

        stopMovieRecordigShowControls()

    } else {

        if !captureSession.outputs.contains(movieFileOutput) {
            return
        }

        // Start recording
        movieFileOutput.connection(with: AVMediaType.video)?.videoOrientation = videoOrientation()

        movieFileOutput.maxRecordedDuration = maxRecordDuration()

        videoFileUrlFromCamera = URL(fileURLWithPath: videoFileLocation())

        if let videoFileUrlFromCamera = videoFileUrlFromCamera {

            movieFileOutput.startRecording(to: videoFileUrlFromCamera, recordingDelegate: self)
        }

    }
}

我该如何解决这个问题?

更新 我还尝试将整个代码包装在 DispatchQueue 中,但出现 Cannot return expression of type () to return type AVCaptureVideoOrientation:

的编译错误
func videoOrientation() -> AVCaptureVideoOrientation {

    DispatchQueue.main.async {

        var videoOrientation: AVCaptureVideoOrientation!

        let orientation: UIDeviceOrientation = UIDevice.current.orientation

        switch orientation {

        case .faceUp, .faceDown, .unknown:

            let interfaceOrientation = UIApplication.shared.statusBarOrientation

            switch interfaceOrientation {

            case .portrait, .portraitUpsideDown, .unknown:
                videoOrientation = .portrait
            case .landscapeLeft:
                videoOrientation = .landscapeRight
            case .landscapeRight:
                videoOrientation = .landscapeLeft
            @unknown default:
                break
            }
            break
        case .portrait, .portraitUpsideDown:
            videoOrientation = .portrait
        case .landscapeLeft:
            videoOrientation = .landscapeRight
        case .landscapeRight:
            videoOrientation = .landscapeLeft
        @unknown default:
            break
        }

        return videoOrientation
    }
}

在主线程中分派其他代码使值 var videoOrientation: AVCaptureVideoOrientation! 成为 nil 当你 return 它作为 return 在切换之前触发,最好是确保从主线程调用整个 startRecording(),如

DispatchQueue.main.async {
    self.startRecording()
}

由于权限检查的关闭在后台线程中运行,因此您需要在 DispatchQueue.main.async

中调度录音调用