如何停止collectionView单元中的相机滞后?

时间:2018-08-24 21:00:58

标签: ios swift avfoundation grand-central-dispatch avcapturesession

我有一个collectionView,其中的单元格充当屏幕。打开应用程序后,当我向相机单元滑动时,会出现一秒钟的延迟,然后在来回滑动的过程很顺畅,下面是此延迟的视频。是否有任何方法可以防止此操作在到达单元之前在后台启动捕获会话?谢谢您的帮助。

enter image description here

相机单元的代码

import UIKit
import AVFoundation


class MainCameraCollectionViewCell: UICollectionViewCell {

    var captureSession = AVCaptureSession()
    private var sessionQueue: DispatchQueue!
    var captureConnection = AVCaptureConnection()

    var backCamera: AVCaptureDevice?
    var frontCamera: AVCaptureDevice?
    var currentCamera: AVCaptureDevice?

    var photoOutPut: AVCapturePhotoOutput?

    var cameraPreviewLayer: AVCaptureVideoPreviewLayer?

    var image: UIImage?

    var usingFrontCamera = false

    override func awakeFromNib() {
        super.awakeFromNib()
        setupCaptureSession()
        setupDevice()
        setupInput()
        self.setupPreviewLayer()
        startRunningCaptureSession
    }

    func setupCaptureSession(){
        captureSession.sessionPreset = AVCaptureSession.Preset.photo
        sessionQueue = DispatchQueue(label: "session queue")
    }

    func setupDevice(usingFrontCamera:Bool = false){
        DispatchQueue.main.async {
            //sessionQueue.async {
            let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)
            let devices = deviceDiscoverySession.devices

            for device in devices{
                if usingFrontCamera && device.position == AVCaptureDevice.Position.front {
                    //backCamera = device
                    self.currentCamera = device
                } else if device.position == AVCaptureDevice.Position.back {
                    //frontCamera = device
                    self.currentCamera = device
                }
            }
        }
    }
    func setupInput() {
        DispatchQueue.main.async {
            do {
                let captureDeviceInput = try AVCaptureDeviceInput(device: self.currentCamera!)
                if self.captureSession.canAddInput(captureDeviceInput) {
                    self.captureSession.addInput(captureDeviceInput)
                }
                self.photoOutPut = AVCapturePhotoOutput()
                self.photoOutPut?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
                if self.captureSession.canAddOutput(self.photoOutPut!) {
                    self.captureSession.addOutput(self.photoOutPut!)
                }
            } catch {
                print(error)
            }
        }
    }
    func setupPreviewLayer(){
        cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
        cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
        cameraPreviewLayer?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        self.layer.insertSublayer(cameraPreviewLayer!, at: 0)
    }

    func startRunningCaptureSession(){
        captureSession.startRunning()
    }

    @IBAction func cameraButton_Touched(_ sender: Any) {
        let settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
        //
        settings.isAutoStillImageStabilizationEnabled = true
        if let photoOutputConnection = self.photoOutPut?.connection(with: .video){
            photoOutputConnection.videoOrientation = (cameraPreviewLayer?.connection?.videoOrientation)!
        }
    }



    @IBAction func Flip_camera(_ sender: UIButton?) {
        print("Flip Touched")

        self.captureSession.beginConfiguration()
         if let inputs = self.captureSession.inputs as? [AVCaptureDeviceInput] {
            for input in inputs {
                self.captureSession.removeInput(input)
                print("input removed")
            }
            //This seemed to have fixed it
            for output in self.captureSession.outputs{
                captureSession.removeOutput(output)
                print("out put removed")
            }
        }


        self.usingFrontCamera = !self.usingFrontCamera
        self.setupCaptureSession()
        self.setupDevice(usingFrontCamera: self.usingFrontCamera)
        self.setupInput()
        self.captureSession.commitConfiguration()
        self.startRunningCaptureSession()
    }

}

1 个答案:

答案 0 :(得分:1)

初始化相机需要时间。一旦您的应用请求使用摄像头,则必须在后台初始化支持软件,但这实际上并不能加快速度。

我建议将与AVFoundation相关的所有内容放在后台线程中,并在应用加载后对其进行初始化。这样,一旦用户准备好滑动到相机单元,便可以为用户准备好相机。如果您不想预加载,则至少仍可以将AVFoundation放在后台,并利用某种活动指示器向用户显示正在加载某些内容,而不仅仅是在相机启动时阻止主线程上。