Adding Multiple Key-Value Pairs to QR Code

2019-08-01 04:50发布

I'm creating QR Codes in my app and I'm wanting to know if it's possible to add a second key-value pair. Right now I have a 12 digit number for the "inputMessage" key and I'm wanting to have some other data for another key. For example, using another string for a new key called "gym".

Here is my function for creating the QR Code:

func generateCode() {
        let gymData = gymName.dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false)
        let codeNumberData = generateRandomNumber(12).dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false)

        let filter = CIFilter(name: "CIQRCodeGenerator")
        filter?.setValue(codeNumberData, forKey: "inputMessage")
        // filter?.setValue(gymData, forKey: "gym")
        filter?.setValue("Q", forKey: "inputCorrectionLevel")

        let qrCodeImage = filter?.outputImage
        let context = CIContext(options: nil)
        let cgImage = context.createCGImage(qrCodeImage!, fromRect: (qrCodeImage?.extent)!)

        let image = UIImage(CGImage: cgImage, scale: 1.0, orientation: .Up)
        let resized = resizeImage(image, withQuality: CGInterpolationQuality.None, rate: 5.0)
        codeImageView.image = resized
    }

1条回答
Animai°情兽
2楼-- · 2019-08-01 04:52

The CIFilter is only expecting to generate the QR code from inputMessage, so you need to create a single aggregate inputMessage and pass that to the filter. One fairly straight forward way of doing this is to create a Dictionary from your inputs, serialize it into a NSData blob using the NSKeyedArchiver, and then set the result as your inputMessage.

func generateCode() {
    var aggregateData = [String: NSData]()

    if let gymData = gymName.dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false) {
        aggregateData.updateValue(gymData, forKey: "gymData")
    }

    if let codeNumberData = generateRandomNumber(12).dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false) {
        aggregateData.updateValue(codeNumberData, forKey: "codeNumberData")
    }

    let archived = NSKeyedArchiver.archivedDataWithRootObject(aggregateData)
    let filter = CIFilter(name: "CIQRCodeGenerator")

    filter?.setValue(archived, forKey: "inputMessage")
    filter?.setValue("Q", forKey: "inputCorrectionLevel")

    let qrCodeImage = filter?.outputImage
    let context = CIContext(options: nil)
    let cgImage = context.createCGImage(qrCodeImage!, fromRect: (qrCodeImage?.extent)!)

    let image = UIImage(CGImage: cgImage, scale: 1.0, orientation: .Up)
    let resized = resizeImage(image, withQuality: CGInterpolationQuality.None, rate: 5.0)
    codeImageView.image = resized
}

Of course this means that on the receiving end, you'll need to expect the payload to be a dictionary, and access the individual components by their keys. Should look something like this.

guard let inputData = scannedQrString.dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false),
    dictionary = NSKeyedUnarchiver.unarchiveObjectWithData(inputData) as? [String: NSData] else {
    return
}

let gymData = dictionary["gymData"]
let codeNumberData = dictionary["codeNumberData"]
查看更多
登录 后发表回答