Building iOS QR Code Scanner with SwiftUI on M1 Mac

SwiftUI is a powerful UI framework for building native apps for any Apple platform. This article guides you through the process of creating an iOS QR code scanner using SwiftUI, Dynamsoft Camera Enhancer and Dynamsoft Barcode Reader on M1 Mac mini.

ios swiftui camera qr code scanner

Dev Environment on M1 Mac mini

  • Xcode 13.2.1
  • Cocoapods

    1. Install Homebrew:

       /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
      
    2. The official way of installing CocoaPods is sudo gem install cocoapods. However, if you are using an M1 Mac, you’d better substitute Ruby install with Homebrew to avoid dependency installation failure:

       brew install cocoapods
      
  • Dynamsoft Camera Enhancer and Dynamsoft Barcode Reader for iOS

    1. Create a Podfile in your project root directory:

       pod init
      
    2. Add dependencies to Podfile:

       platform :ios, '9.0'
      
       target 'qrscanner' do
         use_frameworks!
              
         pod 'DynamsoftCameraEnhancer','2.1.1'
         pod 'DynamsoftBarcodeReader','8.9.1'
       end
      
    3. Install dependencies:

       pod install
      

    Note: you need to apply for a license key to activate the barcode SDK:

        
      let barcodeReader = DynamsoftBarcodeReader.init(license: "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==")                           
            
    

Project Configuration in Xcode 13.2.1

  1. After running pod install, we can start the Xcode project as follows:

     open qrscanner.xcworkspace
    
  2. Go to Signing & Capabilities editor to select a team.
  3. Add camera access permission.

    There is no Info.plist file in Xcode 13.2.1. You need to find TARGETS > Info and then add keys:

     Privacy - Camera Usage Description
    

    iOS camera access permission

Implementing iOS SwiftUI Camera

Dynamsoft Camera Enhancer provides a camera view that can be used to start a camera session with a few lines of Swift code. If you prefer Storyboard, you can follow the online example to learn how to use the API. If SwiftUI is your first choice, you can follow my steps to implement a simple iOS camera app.

4 Steps to Open Camera in SwiftUI

  1. Create a new iOS SwiftUI project named qrscanner.
  2. Create a CameraManager.swift file, which contains a camera view and a callback function for continuously receiving camera frames:

     import Foundation
     import UIKit
     import DynamsoftCameraEnhancer
        
     class CameraManager: NSObject, ObservableObject, DCEFrameListener {
    
         private var dce: DynamsoftCameraEnhancer! = nil
         private var dceView: DCECameraView! = nil
            
         init(frame: CGRect) {
             super.init()
             configureDCE(frame: frame)
         }
            
         func configureDCE(frame: CGRect) {
           dceView = DCECameraView.init(frame: frame)
           dce = DynamsoftCameraEnhancer.init(view: dceView)
           dce.open()
           dce.setFrameRate(30)
             dce.addListener(self)
         }
            
         func getCameraView() -> DCECameraView { 
             return dceView
         }
            
         func frameOutPutCallback(_ frame: DCEFrame, timeStamp: TimeInterval) {
    
         }
     }
    
    

    The ObservableObject protocol is used with the CameraManager class to make the CameraManager instance observed inside the SwiftUI view.

  3. The DCECameraView is a UIKit view. To integrate it into SwiftUI, we use UIViewRepresentable to create and manage the UIView object:

     import Foundation
     import SwiftUI
     import DynamsoftCameraEnhancer
        
     struct CameraView: UIViewRepresentable {
         var cameraManager: CameraManager
         func makeUIView(context: Context) -> DCECameraView {
             let dceView = cameraManager.getCameraView()
             return dceView
         }
        
         func updateUIView(_ uiView: DCECameraView, context: Context) {
                
         }
     }
    
  4. Go to ContentView.swift to instantiate CameraManager and add CameraView to the UI layout:

     import SwiftUI
     import DynamsoftCameraEnhancer
        
     struct ContentView: View {
         @ObservedObject private var cameraManager = CameraManager(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
            
         var body: some View {
             ZStack() {
                 CameraView(cameraManager: cameraManager)
             }
         }
     }
    

Turning iOS Camera into iOS QR Code Scanner

A simple SwiftUI camera app is done. Now we need to turn it into a QR code scanner.

2 Steps to Integrate QR Code Scanning into the SwiftUI Camera View

  1. Decode the QR code from the camera frame and assign the decoding results to a @Published variable in the frameOutPutCallback function:

     @Published var results = "No QR Code found"
     func frameOutPutCallback(_ frame: DCEFrame, timeStamp: TimeInterval) {
         var image:UIImage!
         image = frame.toUIImage()
         let results = try! barcodeReader.decode(image, withTemplate: "")
         var output = "No QR Code found"
         if (results.count > 0) {
             output = ""
             for item in results {
                 let format = item.barcodeFormatString ?? ""
                 let text = item.barcodeText ?? ""
                 output += "Format: " + format + ", Text: " + text + " \n\n "
             }
         }
            
         DispatchQueue.main.async {
             self.results = output
         }
     }
    
  2. Add a Text view to the SwiftUI view hierarchy to display the decoding results:

     struct ContentView: View {
         @ObservedObject private var cameraManager = CameraManager(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))        
         var body: some View {
             ZStack() {
                 CameraView(cameraManager: cameraManager)
                 Text(cameraManager.results).font(.subheadline).foregroundColor(.blue).fontWeight(.heavy)
             }
         }
     }
    

We can now test the iOS QR code scanner on iPhone or iPad.

Source Code

https://github.com/yushulx/ios-swiftui-camera-qr-code-scanner