Barzille Barzille - 1 month ago 13
Swift Question

Sending an on-the-fly created QR Code UIImage by AirDrop fails

I am creating a QR Code on the fly and storing it as UIImage. Now I want to be able to send it using the UIActivityViewController but somehow it fails:

func generateQRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)

if let filter = CIFilter(name: "CIQRCodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 3, y: 3)

if let output = filter.outputImage?.applying(transform) {
return UIImage(ciImage: output)
}
}

return nil
}


And then I am calling the function and store it as UIImage:

let image = generateQRCode(from: "Create my Code")
imgQRCode.image = image


The export button uses the following action:

@IBAction func shareButtonClicked(sender: UIButton) {

let objectsToShare = [imgQRCode.image!] as [AnyObject]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

activityVC.popoverPresentationController?.sourceView = sender
self.present(activityVC, animated: true, completion: nil)

}


After choosing to send via AirDrop to my Mac the app crashes

2016-11-05 23:29:15.912242 Ordnung[3945:888442] CGContextScaleCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.


Nov 5 23:29:15 Ordnung[3945] : CGContextScaleCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

2016-11-05 23:29:15.912396 Ordnung[3945:888442] CGContextTranslateCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Nov 5 23:29:15 Ordnung[3945] <Error>: CGContextTranslateCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
2016-11-05 23:29:15.912584 Ordnung[3945:888442] CGContextConcatCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Nov 5 23:29:15 Ordnung[3945] <Error>: CGContextConcatCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
2016-11-05 23:29:15.912692 Ordnung[3945:888442] CGContextDrawImage: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Nov 5 23:29:15 Ordnung[3945] <Error>: CGContextDrawImage: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
2016-11-05 23:29:15.927580 Ordnung[3945:888442] [AirDrop] Sender kSFOperationEventErrorOccured {
Error = "Error Domain=SFOperation Code=-5 \"Die \U00dcbertragung ist fehlgeschlagen, da du eine ung\U00fcltige Datei senden wolltest.\" UserInfo={NSLocalizedDescription=Die \U00dcbertragung ist fehlgeschlagen, da du eine ung\U00fcltige Datei senden wolltest.}";
SessionID = 76FBE80074FC;
}


Does anybody have an idea on how to get this done?

Cheers Maik

Answer

It seems I need to provide the image in a slightly different way, so altering the QR code generation this way solves the problem by creating a CGImage before creating the UIImage:

func generateQRCode(from string: String) -> UIImage? {
    let ciContext = CIContext()
    let data = string.data(using: String.Encoding.ascii)

    if let filter = CIFilter(name: "CIQRCodeGenerator") {
        filter.setValue(data, forKey: "inputMessage")
        let transform = CGAffineTransform(scaleX: 3, y: 3)
        let upScaledImage = filter.outputImage?.applying(transform)


        let cgImage = ciContext.createCGImage(upScaledImage!,
                                              from: upScaledImage!.extent)
        qrcodeImage = UIImage(cgImage: cgImage!)
        return qrcodeImage
    }
    return nil
}

And additionally you should use a png or jpg representation of the image:

func share() {
    let png = UIImagePNGRepresentation(qrcodeImage)
    let vc = UIActivityViewController(activityItems: [png!], applicationActivities: [])
    present(vc, animated: true)
}