Generating Basic QR Codes in Swift 3.0

QR codes are a type of 2D barcode that was originally developed for use in the Japanese car industry. Encoding URLs, promoting virtual stores, accessing cryptocurrency wallets, adding new contacts to messaging platforms — QR codes (or some variants of them) provide a streamlined approach to working with various types of data.

Facebook’s take on a QR code v. The Snapcode

Lets look at using static data to create our code — for example, a String.

Thanks to the Core Image framework, generating a simple QR code takes only a few lines of code

In the code above we’ve created a function called generateQRCode(from:) which returns an optional UIImage.

In this function, we first want to convert our string to a Data object (which is simply a MutableCollection of bytes). This object will contain our string’s representation using some given encoding. In this case, we use ISO Latin 1; however, ASCII or UTF-8 works too.

This is the heart of QR code generation

Now, create an instance of CoreImage filter using the parameter name “CIQRCodeGenerator.”

Essentially, we’ve initialized a CIFilter object, one for the specific filter called “CIQRCodeGenerator.” This parameter name lets us reference Swift’s built-in filter for QR code generation through the Core Image framework. After creating a filter with the CIFilter method in Swift, you must call setDefaults() or setValue(_:forKey:) to set parameters individually.

Core Image Filter Reference: CIQRCodeGenerator

After creating a filter with the CIFilter method in Swift, you must call setDefaults() or setValue(_:forKey:) to set parameters individually.

This might seem esoteric, to some degree, and it probably should, given the underlying levels of complexity. Take a closer look at the next line:

Data, in this case, is our function’s string argument

Here, we pass our data constant — which is simply an encoded version of our string — to set the value for the key “inputMessage.” This step is crucial and it works in this manner because the parameters of a CIFilter object are set and retrieved through the use of key-value pairs.

Done! Well, not quite.

To recap, we’ve passed our generateQRCode(from:) function a string which we’ve then encoded into a data object. Then, we’ve created a CIFilter object of the specific kind “CIQRCodeGenerator.” Finally, we’ve used our data object to set the value for the key “inputMessage” which represents the data input used in our QR code generation. Essentially, we’ve retrieved a specific template, gathered all of the necessary components, but still haven’t returned anything.

We create our final CIImage by applying a transform and return it as a UIImage

Don’t worry about the transform nonsense; we’ll get to that in just a moment (we’re using it to get rid of the blur in our resulting QR code).

Focus on unwrapping the output. Why are we doing this? It’s because filter — which is our CIFilter — returns an optional CIImage (again, feel free to disregard the .applying(transform) at the end there, for now).

In this particular case, CIFilter ultimately produces a CIImage object using a string as an input. In order to have the image properly displayed in the imageView outlet, we cast it as a UIImage. Finally, we get the following:

Core Image + a few lines of code + some logic = 🔳

Oh no! Why is our QR code so freaking blurry? Since our CIImage is made up of points, the resulting UIImage is scaled to fit our UIImageView, which results in a lack of clarity. This is where the transform part comes in!

Note that the current scale is set to x: 1, y: 1 — this is exactly what we’ll be working with to fix this blur

We create an affine transformation matrix which we will use to scale our QR code. This is simply a struct used in drawing 2D graphics. In short, this matrix links two coordinate systems by specifying how points in one coordinate system map to points in another. Then, we apply it when we unwrap the resulting optional CIImage.

The key here are the two scale values — x and y. We’ve set them both to 1, and this is precisely the reason why we’ve created a QR code of such exceptionally poor quality. What if we try changing both values (scaleX and scaleY) to 100?

Now that’s what I’m talking about!

We’ve successfully scaled up our UIImage. To be honest, we’ve simply used an arbitrarily large number. If we want to be more elaborate with the scaling, we can figure out our desired scaling factor programmatically. So what is this scaling factor?

Well, actually, it’s always equal to the ratio of an image view’s width and the original QR code’s width. In our example, this translates to:

In order to get the width and height of our QR code, we create a CIImage and assign it to the qrCodeImage variable

We’ve added three new lines of code. First, we’ve created a CIImage object by calling outputImage on our CIFilter object. Since this method returns an optional value, we’ve unwrapped it using a guard statement. Next, we’ve set up two constants for our two axes (x and y). As mentioned above, scaleX and scaleY are simply equal to the ratios of our image view’s width and height and our QR code’s width and height, respectively. Finally, we’ve passed these two ratios as parameters to CGAffineTransform to get an adequately scaled affine transformation matrix (i.e. transform). We then call applying(transform) on our outputImage to get the following result:

Finally, we have a usable QR code image!

Another thing we could’ve done during our QR code generation is set the value for error correction. This is done via the key “inputCorrectionLevel.”

Similarly to how we’ve used setValue for “inputMessage,” we call setValue to pass a value to “inputCorrectionLevel”

This parameter controls the amount of additional data encoded in the output image to provide error correction. It is equal to “M” by default, and changing this parameter affects the resulting QR code shape. Higher levels result in larger output images but allow larger areas of the code to be damaged.

Here you can see the effects of using different input correction levels. Note: we have not changed the data input (string)

That’s it for the basics! You have now mastered QR code generation in Swift.

There’s a lot more to QR codes in Swift, but this is it for our tutorial. Thank you for reading this simple overview of QR generation in Swift!