ProjektWeinheim
ProjektWeinheim

Reputation: 201

Pass image from photoOutput(didFinishProcessingPhoto) in PhotoCaptureDelegate.swift to my ViewController

In PhotoCaptureDelegate.swift, I have this function:

/// - Tag: DidFinishProcessingPhoto
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    photoProcessingHandler(false)

    print("photo output called")

    if let error = error {
        print("Error capturing photo: \(error)")
    } else {
        photoData = photo.fileDataRepresentation()    
    }
}

I want the photoData as a static preview image in my UIView in my ViewController after I took a photo. I tried to pass the photoData to a variable in my ViewController or call a function and set it, but the UIElements are nil when I call it from PhotoCaptureDelegate.swift.

How can I use the photoData as a preview image, when the didFinishProcessingPhoto function is called in a delegate?

In case it is relevant, this is how I take a photo:

@IBAction func buttonTakePhotoTapped(_ sender: UIButton) {
    let videoPreviewLayerOrientation = viewPreview.videoPreviewLayer.connection?.videoOrientation

    sessionQueue.async {
        if let photoOutputConnection = self.photoOutput.connection(with: .video) {
            photoOutputConnection.videoOrientation = videoPreviewLayerOrientation!
        }

        let photoSettings = AVCapturePhotoSettings()

        if self.videoDeviceInput.device.isFlashAvailable {
            photoSettings.flashMode = .auto
        }

        photoSettings.photoQualityPrioritization = self.photoQualityPrioritizationMode

        let photoCaptureProcessor = PhotoCaptureProcessor(with: photoSettings, willCapturePhotoAnimation: {
            // Flash the screen to signal that AVCam took a photo.
            DispatchQueue.main.async {
                self.viewPreview.videoPreviewLayer.opacity = 0
                UIView.animate(withDuration: 0.25) {
                    self.viewPreview.videoPreviewLayer.opacity = 1
                }
            }
        }, livePhotoCaptureHandler: { capturing in
            self.sessionQueue.async {
            }
        }, completionHandler: { photoCaptureProcessor in
            // When the capture is complete, remove a reference to the photo capture delegate so it can be deallocated.
            self.sessionQueue.async {
                self.inProgressPhotoCaptureDelegates[photoCaptureProcessor.requestedPhotoSettings.uniqueID] = nil
            }
        }, photoProcessingHandler: { animate in
            }
        )

        // The photo output holds a weak reference to the photo capture delegate and stores it in an array to maintain a strong reference.
        self.inProgressPhotoCaptureDelegates[photoCaptureProcessor.requestedPhotoSettings.uniqueID] = photoCaptureProcessor
        self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureProcessor)
    }
}

Upvotes: 0

Views: 674

Answers (1)

Frank Rupprecht
Frank Rupprecht

Reputation: 10418

You initialize the PhotoCaptureProcessor with several callback blocks that get called at different stages of the capture process. In the completionHandler you should be able to access the captured photo from the photoCaptureProcessor. Something like this:

let photoCaptureProcessor = PhotoCaptureProcessor(with: photoSettings, willCapturePhotoAnimation: {
    // ...
}, livePhotoCaptureHandler: { capturing in
    // ...
}, completionHandler: { photoCaptureProcessor in
    let capturedImage = UIImage(data: photoCaptureProcessor.photoData)
    // be sure to perform UI changes in main thread
    DispatchQueue.main.async {
        // assuming the image view is named like that...
        self.imageView.image = capturedImage
    }

    // ...
}, photoProcessingHandler: { animate in
    // ...
})

Upvotes: 1

Related Questions