【问题标题】:Make UIViewController conform AVCapturePhotoCaptureDelegate not working使 UIViewController 符合 AVCapturePhotoCaptureDelegate 不起作用
【发布时间】:2019-01-22 16:15:03
【问题描述】:

我正在开发使用照片输出来捕捉照片的自定义相机。

当用户点击捕获按钮时,photoOutput.capturePhoto(with: settings, delegate: self)被调用,它的第二个参数为self代表UIViewController,因为UIViewController符合AVCapturePhotoCaptureDelegate

但是,使用消息实现func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) 时会出现 1 个奇怪的警告 -

实例方法 'photoOutput(:didFinishProcessingPhoto:error:)' 几乎匹配协议 'AVCapturePhotoCaptureDelegate' 的可选要求 'photoOutput(:didFinishProcessingPhoto:error:)'

此外,当点击带有错误消息的捕获按钮时会发生崩溃 -

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] 如果您在设置中指定非零格式字典,则您的代理必须响应选择器 captureOutput:didFinishProcessingPhoto :错误:

即使设置的格式字典不是 nil。

但是当我实现一个符合 AVCapturePhotoCaptureDelegate 的自定义类时,没有任何警告,并且运行良好。

所以我很好奇.. UIViewController 不应该符合 AVCapturePhotoCaptureDelegate 吗?如果不是,为什么?

错误示例:

final class CameraViewController: UIViewController, AVCapturePhotoCaptureDelegate {
   ...
   @IBAction func captureButtonDidTap(_ sender: UIButton) {
        guard isSessionRunning else { return }

        if let previewLayerOrientation = previewLayer?.connection?.videoOrientation {
            let photoOutputConnection = photoOutput?.connection(with: .video)
            photoOutputConnection?.videoOrientation = previewLayerOrientation
        }

        guard let photoOutput = self.photoOutput else { return }

        let settings = AVCapturePhotoSettings()

        photoOutput.capturePhoto(with: settings, delegate: self)
    }

    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        if let error = error {
            print(error)
            return
        }
    }
   ...
}

做得好的例子:

final class CameraViewController: UIViewController {
   ...
   @IBAction func captureButtonDidTap(_ sender: UIButton) {
        guard isSessionRunning else { return }

        guard let photoOutput = self.photoOutput else { return }

        let settings = AVCapturePhotoSettings()
        let processor = CameraCaptureProcessor(photoOutput: photoOutput, settings: settings)
        self.capturedDelegate = processor

        processor.capturePhoto()
    }
   ...
}

final class CameraCaptureProcessor: NSObject, AVCapturePhotoCaptureDelegate {
    private var photoOutput: AVCapturePhotoOutput!
    private(set) var settings: AVCapturePhotoSettings!

    convenience init(photoOutput: AVCapturePhotoOutput, settings: AVCapturePhotoSettings) {
        self.init()
        self.photoOutput = photoOutput
        self.settings = settings
    }

    func capturePhoto() {
        photoOutput.capturePhoto(with: settings, delegate: self)
    }

    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        if let error = error {
            print(error)
            return
        }
    }
}

【问题讨论】:

    标签: swift uiviewcontroller camera


    【解决方案1】:

    虽然这篇文章发布已经快一年了,但在我经历了完全相同的事情之后,我才发现它,这让我困惑了几个小时,然后才找到解释。

    我在关注一个可以在 here 找到的旧示例。

    对我来说,问题是由于 Swift 模块造成的。示例中自定义Error通过以下方式引入

    class CameraController: NSObject, AVCapturePhotoCaptureDelegate {
    
        enum Error: Swift.Error {
    
            case noDeviceAvailable
    
            case captureSessionMissing
    
        }
    ... 
    

    通过遵守委托协议,在CameraController范围内实现方法

    class CameraController: NSObject, AVCapturePhotoCaptureDelegate {
    
        ...
    
        //MARK: - AVCapturePhotoCaptureDelegate
    
        func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { ... }
    
        ...
    

    您实际上导致编译器触发警告,因为委托方法中的 Error 类型与范围内可用的 CameraController.Error 类型不匹配。

    解决方案是将自定义 Error 定义移到类范围之外,或者明确告诉编译器委托方法使用 Swift.Error 本身

    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Swift.Error?) { ... }
    

    【讨论】:

    • 感谢您发布此信息!它真的帮助了我!
    猜你喜欢
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2014-02-19
    • 1970-01-01
    相关资源
    最近更新 更多