The way you implemented the toggle camera is just ok and only works if you have only one video AVCaptureDevice input. Think in the case of having multiple AVCaptureDevice inputs(audio and video). In that case you can't guarantee below line -:
let currentCameraInput: AVCaptureInput = session.inputs[0] as! AVCaptureInput
session.removeInput(currentCameraInput)
In this case When you click on toggleCamera button , it crashes with below error
Couldn't add back facing video input
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** Multiple audio/video AVCaptureInputs are not currently supported.'
*** First throw call stack:
(0x38f2f2a3 0x3725997f 0x39aff977 0x39aff091 0xe943d 0xe7875 0x3a4de0a5 0x3a4de057 0x3a4de035 0x3a4dd8eb 0x3a4ddde1 0x3a4065f1 0x3a3f3801 0x3a3f311b 0x37cad5a3 0x37cad1d3 0x38f04173 0x38f04117 0x38f02f99 0x38e75ebd 0x38e75d49 0x37cac2eb 0x3a4472f9 0xdf1ab 0x36324b20)
To overcome this issue i have implemented it different way. So mine toggle camera code inside CameraController.swift looks like this -:
// toggleCamera basic purpose is to toggle the camera from front to back or vice versa as per user selection
func toggleCamera(){
println("toggleCamera -----")
var error:NSError?
var backCameraDevice:AVCaptureDevice?
var audio:AVCaptureDevice?
var frontCameraDevice:AVCaptureDevice?
var rearCamera: AVCaptureInput?
var frontCamera: AVCaptureInput?
for device in availableCameraDevices as! [AVCaptureDevice] {
if device.position == .Back {
self.backCameraDevice = device
}
else if device.position == .Front {
self.frontCameraDevice = device
}
}
if let validVideoFrontDevice = self.frontCameraDevice {
self.frontCamera = AVCaptureDeviceInput.deviceInputWithDevice(validVideoFrontDevice, error: &error) as! AVCaptureDeviceInput
}
if let validVideoBackDevice = self.backCameraDevice {
self.rearCamera = AVCaptureDeviceInput.deviceInputWithDevice(validVideoBackDevice, error: &error) as! AVCaptureDeviceInput
}
session.beginConfiguration()
let inputs = session.inputs as! [AVCaptureInput]
let newCamera: AVCaptureDevice?
if(currentCameraDevice!.position == AVCaptureDevicePosition.Back){
println("Setting new camera with Front")
newCamera = self.frontCameraDevice
if self.hasFrontCamera {
if let validBackDevice = self.rearCamera {
if contains(inputs, validBackDevice) {
session.removeInput(validBackDevice)
}
}
if let validFrontDevice = self.frontCamera {
if !contains(inputs, validFrontDevice) {
session.addInput(validFrontDevice)
}
}
}
} else {
println("Setting new camera with Back")
newCamera = self.backCameraDevice
if let validFrontDevice = self.frontCamera {
if contains(inputs, validFrontDevice) {
session.removeInput(validFrontDevice)
}
}
if let validBackDevice = self.rearCamera {
if !contains(inputs, validBackDevice) {
session.addInput(validBackDevice)
}
}
}
session.commitConfiguration()
if let validError = error {
println("Device setup error occured \(validError.localizedDescription)")
}
currentCameraDevice! = newCamera!
}
/// The Bool property to determine if current device has front camera.
public var hasFrontCamera: Bool = {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
for device in devices {
let captureDevice = device as! AVCaptureDevice
if (captureDevice.position == .Front) {
return true
}
}
return false
}()
In my view controller:
@IBAction func toggleCamera(sender: UIButton) {
// toggle the camera side
println("toggling the camera side")
self.cameraController.toggleCamera()
}
Hope it helps.
Thanks