You first need to remove the existing AVCameraInput from the AVCaptureSession and then add a new AVCameraInput to the AVCaptureSession. The following works for me (under ARC):
-(IBAction)switchCameraTapped:(id)sender
{
//Change camera source
if(_captureSession)
{
//Indicate that some changes will be made to the session
[_captureSession beginConfiguration];
//Remove existing input
AVCaptureInput* currentCameraInput = [_captureSession.inputs objectAtIndex:0];
[_captureSession removeInput:currentCameraInput];
//Get new input
AVCaptureDevice *newCamera = nil;
if(((AVCaptureDeviceInput*)currentCameraInput).device.position == AVCaptureDevicePositionBack)
{
newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
}
else
{
newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
}
//Add input to session
NSError *err = nil;
AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:&err];
if(!newVideoInput || err)
{
NSLog(@"Error creating capture device input: %@", err.localizedDescription);
}
else
{
[_captureSession addInput:newVideoInput];
}
//Commit all the configuration changes at once
[_captureSession commitConfiguration];
}
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
- (AVCaptureDevice *) cameraWithPosition:(AVCaptureDevicePosition) position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices)
{
if ([device position] == position) return device;
}
return nil;
}