如何停止 collectionView 单元格中的相机延迟?

How do I stop camera lag in a collectionView cell?

我有一个 collectionView,它有充当屏幕的单元格。当我在打开应用程序后滑动到相机单元格时,会有一秒钟的延迟,然后来回平滑地滑动,下面是这个延迟的视频。有没有办法防止这种情况在到达单元格之前在后台启动捕获会话?感谢您的帮助。

相机单元代码

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()
    }

}

初始化相机需要时间。一旦你的应用程序请求使用相机,支持软件必须在后台初始化,这真的不可能加速。

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