Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perform Action When a Barcode Is Scanned Using RSBarcodes

I am building an app that utilizes QR code scanning using RSBarcodes for Swift. What I am trying to do in my ScanViewController is to scan a QR code, validate what was scanned, and then segue with the scanned data. Currently, when a QR code is detected, my UI freezes, and shortly after I get an error and memory dump:

'NSInternalInconsistencyException', reason: 'Only run on the main thread!'.

Maybe this isn't the right place to validate the QR code or isn't the right place to segue, but if not, I'm wondering where the validation and segue should take place. My only other requirement is that the validation only occurs exactly when a QR code is detected.

class ScanViewController: RSCodeReaderViewController{
    // Class Variables
    var finalObject: IBuiltCode?
    let ObjectHelper = ObjectBuilder() // Service to validate and build valid scanned objects

    override func viewDidLoad() {
        super.viewDidLoad()

        self.focusMarkLayer.strokeColor = UIColor.redColor().CGColor
        self.cornersLayer.strokeColor = UIColor.yellowColor().CGColor

        self.tapHandler = { point in
            println(point)
        }

        self.barcodesHandler = { barcodes in
            for barcode in barcodes {
                println("Barcode found: type=" + barcode.type + " value=" + barcode.stringValue)
                if let builtObject = self.ObjectHelper.validateAndBuild(barcode,
                      scannedData: barcode.stringValue){
                    println("Good object.")
                    self.performQR()
                }
            }
        }
    }

    func performQR(){
        performSegueWithIdentifier("toQR", sender: self)
    }
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if (segue.identifier == "toQR"){
            let QRVC: QRViewController = segue.destinationViewController as! QRViewController
            QRVC.receivedObject = finalObject as? QRObject
        }
    }
}
like image 476
Drew Antonich Avatar asked Feb 09 '23 12:02

Drew Antonich


1 Answers

I contacted the developer of RSBarcodes_Swift on this issue thread. In order for any UI operation to execute, it needs to be run on the main thread. For example, the segue function needs to be changed from:

func performQR(){
        self.performSegueWithIdentifier("toQR", sender: self)
}

to

func performQR(){
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.performSegueWithIdentifier("toQR", sender: self)
    })
}

To avoid segueing multiple times while scanning, the call self.session.stopRunning() along with a breakcan be used in the barcodes for loop.

self.barcodesHandler = { barcodes in
    for barcode in barcodes {
        println("Barcode found: type=" + barcode.type + " value=" + barcode.stringValue)
        if let builtObject = self.ObjectHelper.validateAndBuild(barcode,
              scannedData: barcode.stringValue){
            println("Good object.")
            self.finalObject = builtObject
            self.session.stopRunning() // Avoid scanning multiple times
            self.performQR()
            break
        }
    }
}
like image 126
Drew Antonich Avatar answered Feb 24 '23 08:02

Drew Antonich