Swift 使UIViewController符合AVCapturePhotoCaptureDelegate不工作

Swift 使UIViewController符合AVCapturePhotoCaptureDelegate不工作,swift,uiviewcontroller,camera,Swift,Uiviewcontroller,Camera,我正在创建使用照片输出捕捉照片的自定义相机 当用户点击捕获按钮时,调用photoOutput.capturePhoto(with:settings,delegate:self),第二个参数为self表示UIViewController,因为UIViewController符合AVCapturePhotoCaptureDelegate 但是,在实现func photoOutput(uu输出:AVCapturePhotoOutput,didFinishProcessingPhoto-photo:AV

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

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

但是,在实现
func photoOutput(uu输出:AVCapturePhotoOutput,didFinishProcessingPhoto-photo:AVCapturePhoto,error:error?)时会出现一个奇怪的警告,并显示消息-

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

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

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

即使设置的格式字典不是零

但是,当我实现一个符合
avcapturepoticapturedelegate
的自定义类时,没有警告,而且运行良好

所以我很好奇。。不应该
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模块。在本例中,通过以下方式引入了自定义
错误

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
类型不匹配,因此实际上是导致编译器触发警告

解决方案是将自定义
错误
定义移到类的范围之外,或者显式地告诉编译器委托方法使用了
Swift.Error

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

谢谢你发布这个!它真的帮助了我!