onmyway133 / blog

🍁 What you don't know is what you haven't learned
https://onmyway133.com/
MIT License
669 stars 33 forks source link

How to show QR code in SwiftUI #855

Open onmyway133 opened 2 years ago

onmyway133 commented 2 years ago

Use CoreImage to generate QR image

import SwiftUI
import CoreImage.CIFilterBuiltins

struct QRView: View {
    let qrCode: String
    @State private var image: UIImage?

    var body: some View {
        ZStack {
            if let image = image {
                Image(uiImage: image)
                    .resizable()
                    .interpolation(.none)
                    .frame(width: 210, height: 210)
            }
        }
        .onAppear {
            generateImage()
        }
    }

    private func generateImage() {
        guard image == nil else { return }

        let context = CIContext()
        let filter = CIFilter.qrCodeGenerator()
        filter.message = Data(qrCode.utf8)

        guard
            let outputImage = filter.outputImage,
            let cgImage = context.createCGImage(outputImage, from: outputImage.extent)
        else { return }

        self.image = UIImage(cgImage: cgImage)
    }
}
JasonCoombs commented 2 years ago

Thanks for this. Very helpful.

Minor edits were required before your example would build for me. Note that your cgimg variable name must have been changed to cgImage and also I wanted to see this with a PreviewProvider in Xcode, which was easy to add:

import SwiftUI
import CoreImage.CIFilterBuiltins

@main
struct TableViewDemoApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView(qrCode: "Hello, world!")
        }
    }
}

struct ContentView: View {
    let qrCode: String
    @State private var image: UIImage?

    var body: some View {
        ZStack {
            if let image = image {
                Image(uiImage: image)
                    .resizable()
                    .interpolation(.none)
                    .frame(width: 210, height: 210)
            }
        }
        .onAppear {
            generateImage()
        }
    }

    private func generateImage() {
        guard image == nil else { return }

        let context = CIContext()
        let filter = CIFilter.qrCodeGenerator()
        filter.message = Data(qrCode.utf8)

        guard
            let outputImage = filter.outputImage,
            let cgImage = context.createCGImage(outputImage, from: outputImage.extent)
        else { return }

        self.image = UIImage(cgImage: cgImage)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(qrCode: "Hello, world!")
    }
}
image