使UIViewController符合AVCapturePhotoCaptureDelegate无法正常工作

时间:2019-01-22 16:15:03

标签: swift uiviewcontroller camera

我正在创建使用照片输出来捕获照片的自定义相机。

当用户点击捕获按钮时,将调用photoOutput.capturePhoto(with: settings, delegate: self),由于self符合UIViewController,因此它将第二个参数作为表示UIViewController的{​​{1}}。

但是,在通过消息实现AVCapturePhotoCaptureDelegate时出现1个奇怪的警告-

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

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

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

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

但是当我实现符合func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)的自定义类时,没有警告,并且效果很好。

所以我很好奇。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
        }
    }
   ...
}

1 个答案:

答案 0 :(得分:0)

尽管自发布以来已经过去了将近一年,但在经历了完全相同的事情之后,我才才发现它,并且让我困惑了几个小时,然后才得到了解释。

我遵循的是一个古老的示例,可以在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?) { ... }