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
}
}
}
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 break
can 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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With