Double Tap or Use Button To Switch Camera From Back to Front (Xcode 8, Swift 3)

don't see here any problems - here is working solution:

import Foundation
import UIKit
import AVFoundation

class MainViewController: UIViewController {

    var tempImage: UIImageView?

    var captureSession: AVCaptureSession?
    var stillImageOutput: AVCaptureStillImageOutput?
    var videoPreviewLayer: AVCaptureVideoPreviewLayer?
    var currentCaptureDevice: AVCaptureDevice?

    var usingFrontCamera = false


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        loadCamera()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        videoPreviewLayer!.frame = self.cameraPreviewSurface.bounds
    }

    @IBAction func switchButtonAction(_ sender: Any) {
        usingFrontCamera = !usingFrontCamera
        loadCamera()
    }


    func getFrontCamera() -> AVCaptureDevice?{
        let videoDevices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo)


        for device in videoDevices!{
            let device = device as! AVCaptureDevice
            if device.position == AVCaptureDevicePosition.front {
                return device
            }
        }
        return nil
    }

    func getBackCamera() -> AVCaptureDevice{
        return AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
    }



    func loadCamera() {
        if(captureSession == nil){
            captureSession = AVCaptureSession()
            captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
        }
        var error: NSError?
        var input: AVCaptureDeviceInput!

        currentCaptureDevice = (usingFrontCamera ? getFrontCamera() : getBackCamera())

        do {
            input = try AVCaptureDeviceInput(device: currentCaptureDevice)
        } catch let error1 as NSError {
            error = error1
            input = nil
            print(error!.localizedDescription)
        }

        for i : AVCaptureDeviceInput in (self.captureSession?.inputs as! [AVCaptureDeviceInput]){
            self.captureSession?.removeInput(i)
        }
        if error == nil && captureSession!.canAddInput(input) {
            captureSession!.addInput(input)
            stillImageOutput = AVCaptureStillImageOutput()
            stillImageOutput?.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
            if captureSession!.canAddOutput(stillImageOutput) {
                captureSession!.addOutput(stillImageOutput)
                videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
                videoPreviewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
                videoPreviewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
                //self.cameraPreviewSurface.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
                self.cameraPreviewSurface.layer.addSublayer(videoPreviewLayer!)
                DispatchQueue.main.async {
                    self.captureSession!.startRunning()
                }


            }
        }



    }
}

some notes:

cameraPreviewSurface - this is your UIView where camera will show

don't reassign the session, don't just add input, but before add new - remove existing ones,

p.s. code done with swift 3.0.1 / xcode 8.1

Cheers )


Xcode Version : Version 10.1 (10B61)
Swift Version : Swift 4.2
Change AVCaptureSession Capture Source

Refers from Stepan Maksymov Solution
we can simplified by replacing captureSession.inputs

First Create an IBAction Outlet and Connect ViewController to Change Camera View

@IBAction private func changeCamera(_ cameraButton: UIButton) {
    usingFrontCamera = !usingFrontCamera
    do{
        captureSession.removeInput(captureSession.inputs.first!)

        if(usingFrontCamera){
            captureDevice = getFrontCamera()
        }else{
            captureDevice = getBackCamera()
        }
        let captureDeviceInput1 = try AVCaptureDeviceInput(device: captureDevice)
        captureSession.addInput(captureDeviceInput1)
    }catch{
        print(error.localizedDescription)
    }
}

Second step Copy simplified AVCaptureDevice Setting || refer Stepan Maksymov

func getFrontCamera() -> AVCaptureDevice?{
    return AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .front).devices.first
    return nil
}

func getBackCamera() -> AVCaptureDevice?{
    return AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices.first
    return nil
}

You can replace @IBAction with function like so.

func changeCamera(){
    usingFrontCamera = !usingFrontCamera
    do{
        captureSession.removeInput(captureSession.inputs.first!)

        if(usingFrontCamera){
            captureDevice = getFrontCamera()
        }else{
            captureDevice = getBackCamera()
        }
        let captureDeviceInput1 = try AVCaptureDeviceInput(device: captureDevice)
        captureSession.addInput(captureDeviceInput1)
    }catch{
        print(error.localizedDescription)
    }
}

Tags:

Ios

Swift3