如何在Swift中创建一个更改摄像机视图的按钮?

时间:2021-08-31 01:27:16

I would like to know how I could change the camera view when I press a button. At the moment, I am using a boolean var camera = false and when I press a button, I want to change the value to true and get the other camera. But that is not working. I now have this:

我想知道当我按下按钮时如何更改相机视图。目前,我使用布尔var camera = false,当我按下按钮时,我想将值更改为true并获取另一个相机。但这不起作用。我现在有这个:

 @IBAction func changeCamera(sender: AnyObject) {

    camera = true

}

override func viewWillAppear(animated: Bool) {

    captureSession = AVCaptureSession()
    captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
    var captureDevice:AVCaptureDevice! = nil
    //var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if (camera == false){
    let videoDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)


    for device in videoDevices{
        let device = device as AVCaptureDevice
        if device.position == AVCaptureDevicePosition.Front {
            captureDevice = device
            break
        }
    }
    } else {
        var captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

    }

    var error: NSError?
    var input = AVCaptureDeviceInput(device: captureDevice, error: &error)

    if error == nil && captureSession!.canAddInput(input) {
        captureSession!.addInput(input)

        stillImageOutput = AVCaptureStillImageOutput()
        stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
        if captureSession!.canAddOutput(stillImageOutput) {
            captureSession!.addOutput(stillImageOutput)

            previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            previewLayer!.videoGravity = AVLayerVideoGravityResizeAspect
            previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
            previewView.layer.addSublayer(previewLayer)

            captureSession!.startRunning()
        }
    }

}

1 个解决方案

#1


15  

The problem lies where you are setting the camera source.

问题出在您设置相机源的位置。

You are setting it in viewDidAppear which will only be called when the view appears on the device. This is whenever you navigate to that view controller from another or close a presented view controller that is being presented by this one.

您在viewDidAppear中设置它,只有当视图出现在设备上时才会调用它。这是每当您从另一个视图控制器导航到该视图控制器或关闭由此视图控制器呈现的呈现视图控制器时。

My suggestion would be to move the camera selection code into its own function that is called by both viewDidLoad and also whenever the changeCamera action is called.

我的建议是将摄像机选择代码移动到它自己的函数中,该函数由viewDidLoad调用,也可以在调用changeCamera操作时调用。

@IBAction func changeCamera(sender: AnObject?) {
    camera = !camera

    reloadCamera()
}


func viewDidAppear(animated: Bool) {
    // normal code

    reloadCamera()
}

func reloadCamera() {
    // camera loading code
    captureSession = AVCaptureSession()
    captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
    var captureDevice:AVCaptureDevice! = nil
    // var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if (camera == false) {
        let videoDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)


        for device in videoDevices{
            let device = device as AVCaptureDevice
            if device.position == AVCaptureDevicePosition.Front {
                captureDevice = device
                break
            }
        }
    } else {
        var captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    }

    var error: NSError?
    var input = AVCaptureDeviceInput(device: captureDevice, error: &error)

    if error == nil && captureSession!.canAddInput(input) {
    captureSession!.addInput(input)

    stillImageOutput = AVCaptureStillImageOutput()
    stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
    if captureSession!.canAddOutput(stillImageOutput) {
        captureSession!.addOutput(stillImageOutput)

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer!.videoGravity = AVLayerVideoGravityResizeAspect
        previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
        previewView.layer.addSublayer(previewLayer)

        captureSession!.startRunning()
    }
}

Also, an additional improvement would be to use a custom enum to store which camera is currently in use rather than a Boolean. This means you can add to it later say if there was ever a third camera. This would look like:

此外,另一项改进是使用自定义枚举来存储当前使用的相机而不是布尔值。这意味着您可以稍后添加它,如果有第三个相机。这看起来像:

enum CameraType {
    case front
    case back
}

var camera = CameraType.back

I hope this helps, apologies for omitting the full code examples, currently on an iPad but I'll update when I get to a computer.

我希望这有帮助,对于省略完整的代码示例表示歉意,目前在iPad上,但是当我到达计算机时我会更新。


Update

Make sure you remove the previous preview layer from the view before you change the camera.

在更换相机之前,请确保从视图中删除上一个预览图层。

func reloadCamera() {
    captureSession?.stopRunning()
    previewLayer?.removeFromSuperlayer()

    // The rest of the camera loading code...

This should fix your camera freezing issue.

这应该可以解决您的相机冻结问题。

#1


15  

The problem lies where you are setting the camera source.

问题出在您设置相机源的位置。

You are setting it in viewDidAppear which will only be called when the view appears on the device. This is whenever you navigate to that view controller from another or close a presented view controller that is being presented by this one.

您在viewDidAppear中设置它,只有当视图出现在设备上时才会调用它。这是每当您从另一个视图控制器导航到该视图控制器或关闭由此视图控制器呈现的呈现视图控制器时。

My suggestion would be to move the camera selection code into its own function that is called by both viewDidLoad and also whenever the changeCamera action is called.

我的建议是将摄像机选择代码移动到它自己的函数中,该函数由viewDidLoad调用,也可以在调用changeCamera操作时调用。

@IBAction func changeCamera(sender: AnObject?) {
    camera = !camera

    reloadCamera()
}


func viewDidAppear(animated: Bool) {
    // normal code

    reloadCamera()
}

func reloadCamera() {
    // camera loading code
    captureSession = AVCaptureSession()
    captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
    var captureDevice:AVCaptureDevice! = nil
    // var backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if (camera == false) {
        let videoDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)


        for device in videoDevices{
            let device = device as AVCaptureDevice
            if device.position == AVCaptureDevicePosition.Front {
                captureDevice = device
                break
            }
        }
    } else {
        var captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    }

    var error: NSError?
    var input = AVCaptureDeviceInput(device: captureDevice, error: &error)

    if error == nil && captureSession!.canAddInput(input) {
    captureSession!.addInput(input)

    stillImageOutput = AVCaptureStillImageOutput()
    stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
    if captureSession!.canAddOutput(stillImageOutput) {
        captureSession!.addOutput(stillImageOutput)

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer!.videoGravity = AVLayerVideoGravityResizeAspect
        previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
        previewView.layer.addSublayer(previewLayer)

        captureSession!.startRunning()
    }
}

Also, an additional improvement would be to use a custom enum to store which camera is currently in use rather than a Boolean. This means you can add to it later say if there was ever a third camera. This would look like:

此外,另一项改进是使用自定义枚举来存储当前使用的相机而不是布尔值。这意味着您可以稍后添加它,如果有第三个相机。这看起来像:

enum CameraType {
    case front
    case back
}

var camera = CameraType.back

I hope this helps, apologies for omitting the full code examples, currently on an iPad but I'll update when I get to a computer.

我希望这有帮助,对于省略完整的代码示例表示歉意,目前在iPad上,但是当我到达计算机时我会更新。


Update

Make sure you remove the previous preview layer from the view before you change the camera.

在更换相机之前,请确保从视图中删除上一个预览图层。

func reloadCamera() {
    captureSession?.stopRunning()
    previewLayer?.removeFromSuperlayer()

    // The rest of the camera loading code...

This should fix your camera freezing issue.

这应该可以解决您的相机冻结问题。