Search code examples
swiftxcodeavfoundationavcapturesessionibaction

Swift If you specify a non-nil format dictionary in your settings, your delegate must respond to the selector captureOutput:didFinishProcessingPhoto


The code I am using below is supposed to take a photo and then convert the image to base64 in order to send it to a server. The code worked taking the photo, converting it to base64, and uploading it to my server but has stopped working. I have tried using other stack overflow posts to solve this issue but it has not worked for me. Thanks for any responses in advance!

Error

Thread 1: Exception: "*** -[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] If you specify a non-nil format dictionary in your settings, your delegate must respond to the selector captureOutput:didFinishProcessingPhoto:error:, or the deprecated captureOutput:didFinishProcessingPhotoSampleBuffer:previewPhotoSampleBuffer:resolvedSettings:bracketSettings:error:"

Code:

@IBAction func takePhotoButtonPressed(_ sender: Any) {
      let settings = AVCapturePhotoSettings()
      let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
      let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
                           kCVPixelBufferWidthKey as String: 160,
                           kCVPixelBufferHeightKey as String: 160]
      settings.previewPhotoFormat = previewFormat
      sessionOutput.capturePhoto(with: settings, delegate: self)
}
        

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    let imageData = photo.fileDataRepresentation()
    let base64String = imageData?.base64EncodedString()
    print(base64String!)
}

Solution

  • Let's break down the error message:

    • Thread 1: Exception:

      An Objective C exception was thrown from Thread 1 of your program (that's probably the main thread). Not particularly interesting/insightful.

    • -[AVCapturePhotoOutput capturePhotoWithSettings:delegate:]

      This syntax describes the Objective-C method that threw the exception. The method's selector is capturePhotoWithSettings:delegate:, and it belongs to the AVCapturePhotoOutput class. The - indicates that it's an instance method (where a + would have indicated it's a class method).

    • If you specify a non-nil format dictionary in your settings ...`

      This is the case, you called capturePhoto(with: settings, ... with settings that aren't nil.

    • your delegate must respond to the selector captureOutput:didFinishProcessingPhoto:error:

      The system is complaining that you passed a delegate that does not respond to the selector captureOutput:didFinishProcessingPhoto:error: (In Swift, the method is imported as photoOutput(_:didFinishProcessingPhoto:error:)).

      That is, your delegate doesn't define any methods with that name. You decided to pass self (whatever that is, I don't know without context) as the delegate: capturePhoto(..., delegate: self).

      Whatever the type of self is, it already conforms to the AVCapturePhotoCaptureDelegate protocol (or else this would never have compiled). But it does not implement this method, which is optional by the protocol, but mandatory in this context.

    • or the deprecated captureOutput:didFinishProcessingPhotoSampleBuffer:previewPhotoSampleBuffer:resolvedSettings:bracketSettings:error:

      This is just telling you that instead of captureOutput:didFinishProcessingPhoto:error:, you could instead fix this issue by implementing captureOutput:didFinishProcessingPhotoSampleBuffer:previewPhotoSampleBuffer:resolvedSettings:bracketSettings:error:, but since that's deprecated, you probably shouldn't use it.

    So in all, whatever the type of self is, you need to make sure it implements the method photoOutput(_:didFinishProcessingPhoto:error:)