avatar
Published on

How to generate QR codes in SwiftUI

Authors
  • avatar
    Name
    Mick MacCallum
    Twitter
    @0x7fs

The easiest way to generate a QR code in SwiftUI is to use Core Image's CIQRCodeGenerator filter. The process involves creating the filter, providing it with data, and converting the output into a format that SwiftUI can display. Here is an example implementation:

import SwiftUI
import CoreImage.CIFilterBuiltins

struct QRCodeView: View {
    let data: String

    var body: some View {
        Image(uiImage: qrCodeImage)
            .interpolation(.none)
            .resizable()
            .scaledToFit()
    }

    private var qrCodeImage: UIImage {
        let context = CIContext()
        let filter = CIFilter.qrCodeGenerator()

        filter.message = Data(data.utf8)

        if let outputImage = filter.outputImage {
            let transform = CGAffineTransform(scaleX: 10, y: 10)
            let scaledImage = outputImage.transformed(by: transform)

            if let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) {
                return UIImage(cgImage: cgImage)
            }
        }

        return UIImage()
    }
}

The main things to note here:

  1. The filter setup: CIFilter.qrCodeGenerator() gives us the QR code generator.
  2. Data conversion: We need to convert our string to Data for the filter to work.
  3. Scaling: The default QR code is tiny, so I scale it up by 10x to make it actually usable.
  4. Image conversion: Core Image outputs a CIImage, but SwiftUI needs a UIImage, so we convert through CGImage.
  5. Interpolation modifier: The .interpolation(.none) modifier is important because it ensures the QR code image is displayed with sharp, crisp edges. Without this, SwiftUI might apply smoothing or blurring when scaling the image, which can make the QR code unreadable by scanners. Setting interpolation to .none preserves the pixel-perfect quality needed for QR codes to work reliably.

You can drop this into your SwiftUI app like this:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Scan this QR code")
                .font(.headline)
            
            QRCodeView(data: "https://example.com")
                .frame(width: 200, height: 200)
        }
        .padding()
    }
}

Setting the error correction level

Depending on your use case, you may want to set the error correction level. The default is M (Medium), but you can set it to L, Q, or H for different levels of error correction.

The error correction levels are:

  • "L" (Low): 7% recovery capacity - smallest size
  • "M" (Medium): 15% recovery capacity - good balance
  • "Q" (Quartile): 25% recovery capacity - better reliability
  • "H" (High): 30% recovery capacity - most reliable but largest

That's it! QR codes are super useful for sharing links, contact info, or any text data. This approach gives you a solid foundation that you can build on for your own use cases.