Search code examples
iosswiftbarcode-scanner

iOS Swift Scanning Multiple Barcodes


I use the following code to scan barcodes:

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    var highlightViewRect = CGRectZero

    var barCodeObject : AVMetadataObject!

    var detectionString : String!

    let barCodeTypes = [AVMetadataObjectTypeUPCECode,
        AVMetadataObjectTypeCode39Code,
        AVMetadataObjectTypeCode39Mod43Code,
        AVMetadataObjectTypeEAN13Code,
        AVMetadataObjectTypeEAN8Code,
        AVMetadataObjectTypeCode93Code,
        AVMetadataObjectTypeCode128Code,
        AVMetadataObjectTypePDF417Code,
        AVMetadataObjectTypeQRCode,
        AVMetadataObjectTypeAztecCode
    ]


    // The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.

    for metadata in metadataObjects {
        for barcodeType in barCodeTypes {

            if metadata.type == barcodeType {
                barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)

                highlightViewRect = barCodeObject.bounds

                detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue

                let len = detectionString.characters.count
                print("raw=\(detectionString)")
                if len == 25 {
                    detectionString=detectionString.substringWithRange(Range<String.Index>(start: detectionString.startIndex.advancedBy(3), end: detectionString.endIndex.advancedBy(0)))
                } else if len > 22 {
                    detectionString=detectionString.substringWithRange(Range<String.Index>(start: detectionString.startIndex.advancedBy(22), end: detectionString.endIndex.advancedBy(0)))
                }
                print("mod=\(detectionString)")
            }

        }
    }

    self.session.stopRunning()
    sendScan(detectionString)

    self.highlightView.frame = highlightViewRect
    self.view.bringSubviewToFront(self.highlightView)

}

It looks like it should capture multiple barcodes from the same scan. However, it only captures one. I'm sure I'm doing something wrong here but I'm not sure what.


Solution

  • The maximum number of simultaneous detections is 4, this number is only for 2 dimensional barcodes. 1 dimensional barcode recognition is limited to 1 detection. See this reference for more info:

    Apple: Technical Note TN2325

    Running your code (for as far as provided), gets me multiple (2D) detections. Be aware that the sendScan method only sends the last detected item.

    A slight modification to your code :

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
    
        var captures : [String] = []
    
        for metadata in metadataObjects {
    
            var detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue
    
    
            let len = detectionString.characters.count
            print("raw=\(detectionString)")
            if len == 25 {
                detectionString = detectionString.substringWithRange(Range<String.Index>(start: detectionString.startIndex.advancedBy(3), end: detectionString.endIndex.advancedBy(0)))
            } else if len > 22 {
                detectionString = detectionString.substringWithRange(Range<String.Index>(start: detectionString.startIndex.advancedBy(22), end: detectionString.endIndex.advancedBy(0)))
            }
            print("mod=\(detectionString)")
    
    
            captures.append(detectionString)
    
        }
    
        print("Captured \(captures.count) barcodes.")
    
    }
    

    Produces this output:

    raw=www.barcode1.co.za
    mod=www.barcode1.co.za
    raw=http://www.moxx.in
    mod=http://www.moxx.in
    raw=http://www.harrowhouse.com/
    mod=.com/
    raw=Ver1
    mod=Ver1
    Captured 4 barcodes.