When I was developing a QR code scanner and generator as a part of one of my apps, I was a little bit confused. I mean it is really simple to generate QR code in Swift 3.1 like so:

//First convert your string to data
let stringData = someString.data(using: String.Encoding.utf8)
    
//Then use CIFilter to create a CIImage of the QR Code
let filter = CIFilter(name: "CIQRCodeGenerator")
filter?.setValue(stringData, forKey: "inputMessage")
filter?.setValue("H", forKey: "inputCorrectionLevel")
guard let ciImage = filter?.outputImage else { return nil }

//Finally create the well known UIImage
let image = UIImage(ciImage: ciImage)

But when I tried to copy the image to the general UIPasteboard or export it via UIActivityViewController, it would just not work. 🤔

Why? I have no idea! As a good programmer, I asked the guy who knows everything: Google. 🤓

It turned out I wasn’t the only one who had this issue (who has seen that coming?). Though, people did not create UIImages  from CIImages, so suggestions like “Save your UIImage to a file and then you can share it.” would not only not work because UIImagePNGRepresentation(image:) returns nil for UIImages from CIImage but I also did not want to store a file in my documents directory.

I mean why would I? I want to create QR codes with Swift on the fly and then share them via UIPasteboard or  UIActivityViewController . That can’t be that hard, right? 💁

And actually it isn’t hard at all. As suggested by this kind person, all we have to do is to convert the CIImage to a CGImage before creating the UIImage. Woa, so many images. 😨

So here is the final product. A nice function to turn Strings into QR codes in Swift 3.1. I also added a size argument so you can get nice and crisp QR codes of any size you desire. You could for example pass the size of an UIImageView to this function to get a QR code which exactly fits its size.

func generateBarcode(text: String?, size: CGFloat) -> UIImage? {
   
    //Make sure there is a String to work with     
    guard let text = text else { return nil }
        
    //Convert string to data
    let stringData = text.data(using: String.Encoding.utf8)
    
    //Generate CIImage
    let filter = CIFilter(name: "CIQRCodeGenerator")
    filter?.setValue(stringData, forKey: "inputMessage")
    filter?.setValue("H", forKey: "inputCorrectionLevel")
    guard let ciImage = filter?.outputImage else { return nil }
        
    //Scale image to proper size
    let scale = size / ciImage.extent.size.width
    let transform = CGAffineTransform(scaleX: scale, y: scale)
    let scaledCIImage = ciImage.applying(transform)
        
    //Convert to CGImage
    let ciContext = CIContext()
    guard let cgImage = ciContext.createCGImage(scaledCIImage, from: scaledCIImage.extent) else { return nil }
        
    //Finally return the UIImage
    return UIImage(cgImage: cgImage)
}

Yeah, done! Time to celebrate and have some cake. 🎉 🎂 🎊

But wait, what if we need to generate QR codes in various places in our App? Well, in this case, lets just make this an extension on String for our own convenience and reusability. Or should we make it a UIImage initializer? 🤔

I don’t know. Maybe you can tell me which one is better (you know, down there, in the comments 🙃). Anyways, here is the String extension:

extension String {
    
    func qrCode(withSize size: CGFloat) -> UIImage? {
        
        //Get self as data
        let stringData = self.data(using: String.Encoding.utf8)
        
        //Generate CIImage
        let filter = CIFilter(name: "CIQRCodeGenerator")
        filter?.setValue(stringData, forKey: "inputMessage")
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        guard let ciImage = filter?.outputImage else { return nil }
        
        //Scale image to proper size
        let scale = size / ciImage.extent.size.width
        let transform = CGAffineTransform(scaleX: scale, y: scale)
        let scaledCIImage = ciImage.applying(transform)
        
        //Convert to CGImage
        let ciContext = CIContext()
        guard let cgImage = ciContext.createCGImage(scaledCIImage, from: scaledCIImage.extent) else { return nil }
        
        //Finally return UIImage
        return UIImage(cgImage: cgImage)
    }
    
}

And here the UIImage initializer:

extension UIImage {

    convenience init?(qrCode: String?, size: CGFloat) {
        
        //Fail if there is no text
        guard let qrCode = qrCode else { return nil }
        
        //Get self as data
        let stringData = qrCode.data(using: String.Encoding.utf8)
        
        //Generate CIImage
        let filter = CIFilter(name: "CIQRCodeGenerator")
        filter?.setValue(stringData, forKey: "inputMessage")
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        guard let ciImage = filter?.outputImage else { return nil }
        
        //Scale image to proper size
        let scale = size / ciImage.extent.size.width
        let transform = CGAffineTransform(scaleX: scale, y: scale)
        let scaledCIImage = ciImage.applying(transform)
        
        //Convert to CGImage
        let ciContext = CIContext()
        guard let cgImage = ciContext.createCGImage(scaledCIImage, from: scaledCIImage.extent) else { return nil }
        
        //Initialize with CGImage
        self.init(cgImage: cgImage)
    }

}

And last but not least, here’s how you can finally generate a QR code from String and copy it to UIPasteboard on iOS with Swift 3.1 (what a wonderful, SEO optimized sentence ✌️):

let textToCreateQRCodeFor = "Make me a QR code"
let qrCodeImage = UIImage(qrCode: textToCreateQRCodeFor, size: 250.0)
UIPasteboard.general.image = qrCodeImage