I'm trying to implement some custom camera similar to snapchat. I cannot see why my image is always nil during segue. Maybe a fresh pair of eyes may help as I have been working on this for 2 days now...
When I tap the take photo button (to run "livePhotoTapped"), app crashes with error: fatal error: unexpectedly found nil while unwrapping an Optional value, referring to the image being nil
Any help would be nice :)
@IBOutlet weak var cameraView: UIView!
//session to capture data
var captureSession = AVCaptureSession()
//which camera to use
var backFacingCamera: AVCaptureDevice?
var frontFacingCamera: AVCaptureDevice?
var currentDevice: AVCaptureDevice?
var stillImageOutput: AVCaptureStillImageOutput?
var stillImage: UIImage?
//camera preview layer
var cameraPreviewLayer: AVCaptureVideoPreviewLayer?
func setupCaptureSessionCamera() {
//this makes sure to get full res of camera
captureSession.sessionPreset = AVCaptureSession.Preset.photo
var devices = AVCaptureDevice.devices(for: .video)
//query available devices
for device in devices {
if device.position == .front {
frontFacingCamera = device
} else if device.position == .back {
backFacingCamera = device
}
}//end iteration
//set a default device
currentDevice = backFacingCamera
//configure session w output for capturing still img
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput?.outputSettings = [AVVideoCodecKey : AVVideoCodecType.jpeg]
do {
//capture the data from whichevr camera we r using..imagine as buffer to translate data into real world image
let captureDeviceInput = try AVCaptureDeviceInput(device: currentDevice!)
captureSession.addInput(captureDeviceInput)
captureSession.addOutput(stillImageOutput!)
//setup camera preview layer
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
//add the preview to our specified view in the UI
view.layer.addSublayer(cameraPreviewLayer!)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
cameraPreviewLayer?.frame = cameraView.frame
captureSession.startRunning()
} catch let error {
print(error)
}//end do
}
@IBAction func livePhotoTapped(_ sender: UIButton) {
let videoConnection = stillImageOutput?.connection(with: .video)
//capture still image async
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection!, completionHandler: { (imageDataBuffer, error) in
if let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: imageDataBuffer!, previewPhotoSampleBuffer: imageDataBuffer!) {
self.stillImage = UIImage(data: imageData)
self.performSegue(withIdentifier: "toPreviewPhoto", sender: self)
}
})
}
Use like this :
For CMSampleBufferIsValid
check this link
@IBAction func livePhotoTapped(_ sender: UIButton) {
let videoConnection = stillImageOutput?.connection(with: .video)
//capture still image async
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection!, completionHandler: { (imageDataBuffer, error) in
if error != nil {
print("error \(error)")
} else {
if let imageBuffer = imageDataBuffer, CMSampleBufferIsValid(imageBuffer) {
if let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: imageDataBuffer!, previewPhotoSampleBuffer: imageDataBuffer!) {
self.stillImage = UIImage(data: imageData)
self.performSegue(withIdentifier: "toPreviewPhoto", sender: self)
}
} else {
print("imageDataBuffer is nil or not valid")
}
}
})
}