【问题标题】:Can't Restart Capture Session After Dismissing关闭后无法重新启动捕获会话
【发布时间】:2026-02-22 17:25:02
【问题描述】:

我有一个按钮可以启动AVCaptureSession 来扫描条形码。除非您取消session 或扫描条形码并决定扫描另一个条形码,否则一切正常。为了再次启动它,必须关闭视图控制器,然后再次显示。

再次尝试启动会话时的错误在setUpCaptureSession()

let captureSession = AVCaptureSession()
var captureDevice: AVCaptureDevice?
var captureLayer: AVCaptureVideoPreviewLayer?

这里是相关的方法。

@IBAction func scanBarcode(sender: AnyObject) {
        self.setupCaptureSession()
    }

func cancel() {
        NSNotificationCenter.defaultCenter().postNotificationName("backPressed", object: nil, userInfo: nil)
        self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
    }

func cancelBarcodeScan() {
        self.captureSession.stopRunning()
        self.captureLayer?.removeFromSuperlayer()
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "done")
        self.navigationItem.leftBarButtonItem?.action = "cancel"
    }

private func setupPreviewLayer(completion:() -> ()) {
        self.captureLayer = AVCaptureVideoPreviewLayer(session: captureSession)

        if let capLayer = self.captureLayer {
            capLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
            capLayer.frame = self.view.frame
            self.view.layer.addSublayer(capLayer)
            self.navigationItem.rightBarButtonItem = nil
            self.navigationItem.leftBarButtonItem?.action = "cancelBarcodeScan"
            completion()
        } else {
            self.showError("An error occured beginning video capture.")
        }
    }

    private func addMetaDataCaptureOutToSession() {
        let metaData = AVCaptureMetadataOutput()
        self.captureSession.addOutput(metaData)
        // metaData.metadataObjectTypes = metaData.availableMetadataObjectTypes
        metaData.metadataObjectTypes = [AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code,AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypePDF417Code,
            AVMetadataObjectTypeQRCode, AVMetadataObjectTypeAztecCode]
        metaData.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
    }

    private func setupCaptureSession() {
        self.captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        let deviceInput: AVCaptureDeviceInput
        do {
            deviceInput = try AVCaptureDeviceInput(device: captureDevice)
        } catch {
            return
        }

        if (captureSession.canAddInput(deviceInput)) {
            // Show live feed
            captureSession.addInput(deviceInput)
            self.setupPreviewLayer({
                self.captureSession.startRunning()
                self.addMetaDataCaptureOutToSession()
            })
        } else {
            self.showError("Error while setting up input captureSession.")
        }
    }

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        for metaData in metadataObjects {
            let decodedData: AVMetadataMachineReadableCodeObject = metaData as! AVMetadataMachineReadableCodeObject
            upcTextField.text = decodedData.stringValue
            itemNameTextField.text = decodedData.type
            getProductData(decodedData.stringValue)
            self.captureSession.stopRunning()
            self.captureLayer?.removeFromSuperlayer()
            self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "done")
            self.navigationItem.leftBarButtonItem?.action = "cancel"
        }
    }

    private func showError(error:String)
    {
        let alertController = UIAlertController(title: "Error", message: error, preferredStyle: .Alert)
        let dismiss:UIAlertAction = UIAlertAction(title: "Ok", style: .Default, handler:{(alert:UIAlertAction!) in
            alertController.dismissViewControllerAnimated(true, completion: nil)
        })
        alertController.addAction(dismiss)
        self.presentViewController(alertController, animated: true, completion: nil)
    }

【问题讨论】:

标签: ios swift avcapturesession


【解决方案1】:

我遇到了同样的问题,我就是这样解决的,我只是添加了一个 captureSession.stopRunning() captueSession.StartRunning()

 if metadataObj.stringValue != nil {
//                messageLabel.text = metadataObj.stringValue
                let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject

                if supportedCodeTypes.contains(metadataObj.type) {
                    // If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
                    let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
                    qrCodeFrameView?.frame = barCodeObject!.bounds

                    guard let url = URL(string: metadataObj.stringValue!) else {
                            return
                            }
                        if #available(iOS 10.0, *) {
                            performSegue(withIdentifier: "segue", sender: nil)
                            captureSession.stopRunning()
                            captureSession.startRunning()
                            

【讨论】:

    最近更新 更多