Reputation: 1012
I am trying to scan a qr code that I have generated using Adding Multiple Key-Value Pairs to QR Code as a guide. I can generate the qr code, but when I try to scan it, it yields a metadataObj.stringValue of null.
Here is my code to read the metadata output:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects == [] || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
print("No QR code is detected")
return
}
// Get the metadata object.
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
if metadataObj.type == AVMetadataObject.ObjectType.qr {
// If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
if let layer = previewLayer{
let barCodeObject = layer.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
}
guard let inputData = metadataObj.stringValue?.data(using: String.Encoding.isoLatin1, allowLossyConversion: false),
let dictionary = NSKeyedUnarchiver.unarchiveObject(with: inputData) as? [String: NSData] else { return }
print(dictionary["firstName"] ?? "None")
}
}
How do I unarchive the data if the meta data object is outputting a string value of null?
Upvotes: 4
Views: 2876
Reputation: 41
I was able to encode a Swift dictionary into a QR code and decode it from the metadataObject output, using the Codable protocol
Here's the thought process for encoding your data into a QR code:
Here's the code I used to convert a swift dictionary into a QR code:
func generateQRCode(from dictionary: [String:String]) -> UIImage? {
do {
let data = try JSONEncoder().encode(dictionary)
if let validData = String(data: data,encoding: .utf8){
print(validData)
}
if let filter = CIFilter(name: "CIQRCodeGenerator"){
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 10, y: 10)
if let output = filter.outputImage?.transformed(by: transform){
return UIImage(ciImage: output)
}
}
} catch {
print(error.localizedDescription)
}
return nil
}
Here's the thought process for decoding your data from the QR code:
Here's the code I wrote for decoding the QR code back into a Swift dictionary using the QR delegate function metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
.
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
if let metadataObject = metadataObjects.first{
if metadataObject.type == .qr{
let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject
do {
if let validData = readableObject?.stringValue?.data(using: .utf8){
let dict = try JSONDecoder().decode([String:String].self,from:validData)
//do stuff with dict
print(dict)
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
}
} catch {
print(error.localizedDescription)
}
}
}
navigationController?.popViewController(animated: true)
}
Hope that helps anyone still stuck on this question. Codable is very convenient for serializing data types into JSON, which suits QR codes quite well IMO.
Upvotes: 4
Reputation: 49
have you tried to iterate over the dictionary to double check if the value is valid?
perhaps if the lossyconversion is set to false, then the string is set to nil.
Upvotes: 0