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.
Dev Environment on M1 Mac mini
- Xcode 13.2.1
-
Cocoapods
-
Install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
-
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
-
Create a Podfile in your project root directory:
pod init
-
Add dependencies to Podfile:
platform :ios, '9.0' target 'qrscanner' do use_frameworks! pod 'DynamsoftCameraEnhancer','2.1.1' pod 'DynamsoftBarcodeReader','8.9.1' end
-
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
-
After running
pod install
, we can start the Xcode project as follows:open qrscanner.xcworkspace
- Go to
Signing & Capabilities
editor to select a team. -
Add camera access permission.
There is no
Info.plist
file in Xcode 13.2.1. You need to findTARGETS > Info
and then add keys:Privacy - Camera Usage Description
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
- Create a new iOS SwiftUI project named
qrscanner
. -
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 theCameraManager
instance observed inside the SwiftUI view. -
The
DCECameraView
is aUIKit view
. To integrate it into SwiftUI, we useUIViewRepresentable
to create and manage theUIView
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) { } }
-
Go to
ContentView.swift
to instantiateCameraManager
and addCameraView
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
-
Decode the QR code from the camera frame and assign the decoding results to a
@Published
variable in theframeOutPutCallback
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 } }
-
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.
Related Articles
Source Code
https://github.com/yushulx/ios-swiftui-camera-qr-code-scanner