iOS Swift - 如何正确使用 rectOfInterest(条码扫描器)

iOS Swift - How to use rectOfInterest correctly (barcode scanner)

提问人:beks6 提问时间:5/2/2017 最后编辑:Communitybeks6 更新时间:5/2/2017 访问量:6289

问:

我有一个扫描条形码的 iOS 应用程序。

现在我想定义一个特定的扫描区域。为此,我使用了属性和方法。rectOfInterestmetadataOutputRectOfInterest

我面临的问题

当我只使用下面的代码时,如果我删除扫描在整个显示器上工作正常,则不会扫描任何内容barcodeAreaView

class BarcodeReaderViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    // Camera view
    var cameraView: AVCaptureVideoPreviewLayer?
    // AV capture session and dispatch queue
    let captureSession = AVCaptureSession()
    let sessionQueue = DispatchQueue(label: AVCaptureSession.self.description(), attributes: [], target: nil)
    var barcodeAreaView: UIView?

    let supportedCodeTypes = [
        AVMetadataObjectTypeEAN8Code,
        AVMetadataObjectTypeEAN13Code,
        AVMetadataObjectTypeUPCECode,
        AVMetadataObjectTypeCode39Code,
        AVMetadataObjectTypeCode93Code,
        AVMetadataObjectTypeCode128Code,
        AVMetadataObjectTypeCode39Mod43Code,
        AVMetadataObjectTypeInterleaved2of5Code
    ]
    let metadataOutput = AVCaptureMetadataOutput()
    var barcodeArea:CGRect!

    override func viewDidLoad() {
        super.viewDidLoad()

        let width = 250
        let height = 100

        print(self.view.frame.size.width)

        let xPos = (CGFloat(self.view.frame.size.width) / CGFloat(2)) - (CGFloat(width) / CGFloat(2))
        let yPos = (CGFloat(self.view.frame.size.height) / CGFloat(2)) - (CGFloat(height) / CGFloat(2))
        barcodeArea = CGRect(x: Int(xPos), y: Int(yPos), width: width, height: height)

        barcodeAreaView = UIView()
        barcodeAreaView?.layer.borderColor = UIColor.red.cgColor
        barcodeAreaView?.layer.borderWidth = 1
        barcodeAreaView?.frame = barcodeArea
        view.addSubview(barcodeAreaView!)

        captureSession.beginConfiguration()

        let videoDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

        if videoDevice != nil {

            let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice)

            if videoDeviceInput != nil {

                if captureSession.canAddInput(videoDeviceInput) {

                    captureSession.addInput(videoDeviceInput)
                }
            }

            if captureSession.canAddOutput(metadataOutput) {

                captureSession.addOutput(metadataOutput)

                metadataOutput.metadataObjectTypes = supportedCodeTypes
                metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)

                cameraView = AVCaptureVideoPreviewLayer(session: captureSession)
                cameraView?.videoGravity = AVLayerVideoGravityResizeAspectFill
                cameraView?.frame = view.layer.bounds

                metadataOutput.rectOfInterest = cameraView!.metadataOutputRectOfInterest(for: barcodeArea)
                view.layer.addSublayer(cameraView!)
            }
        }

        captureSession.commitConfiguration()
        view.bringSubview(toFront: barcodeAreaView!)
    }

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        // Start AV capture session
        sessionQueue.async {
            self.captureSession.startRunning()
        }
    }

    override func viewWillDisappear(_ animated: Bool) {

        super.viewWillDisappear(animated)

        // Stop AV capture session
        sessionQueue.async {
            self.captureSession.stopRunning()
        }
    }

    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {

        if let metadataObject = metadataObjects.first {

            let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject            
            let message = readableObject.stringValue
            print(message)
        }
    }
}

我已经看过这个问题了

如何使用 metadataOutputRectOfInterestForRect 方法和 rectOfInterest 属性扫描特定区域?(二维码)

我在这里面临的问题是,扫描有点滞后,我的导航控制器无法正常工作(因为侦听器正在等待扫描)

更新:

按照此答案中的建议解决了问题

https://stackoverflow.com/a/37603743/2319900

我在我的之后添加了以下行self.captureSession.startRunning()

metadataOutput.rectOfInterest = cameraView!.metadataOutputRectOfInterest(for: barcodeArea)
iOS的 iPhone Swift3 XCODE8

评论

0赞 RJ168 5/14/2019
为什么这需要写在之后?如果我们在这一行之前编写相同的代码,则将不起作用。self.captureSession.startRunning()

答: 暂无答案