
Barcodes are ubiquitous in today’s world, making them an essential feature for many apps. With AVFoundation in Swift, you can create a powerful barcode scanner app. This guide will walk you through building a simple barcode scanner app, from setting up the project to implementing barcode scanning functionality.
Setting Up the Project
- Open Xcode and Create a New Project:
- Select the “App” template.
- Name your project (e.g., “BarcodeScanner”).
- Choose Swift as the language and SwiftUI as the user interface.
- Configure Privacy Settings:
- Open
Info.plist
. - Add the key
NSCameraUsageDescription
with a description like “We need access to your camera to scan barcodes”.
- Open
Designing the User Interface
- Open
ContentView.swift
and update the code to include a button that starts the scanning process and a text field to display the scanned barcode.
import SwiftUI
struct ContentView: View {
@State private var isShowingScanner = false
@State private var scannedCode = ""
var body: some View {
VStack {
Text("Scanned Barcode:")
.font(.headline)
Text(scannedCode)
.font(.largeTitle)
.padding()
Button(action: {
isShowingScanner = true
}) {
Text("Start Scanning")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.sheet(isPresented: $isShowingScanner) {
ScannerView(scannedCode: $scannedCode)
}
}
}
Creating the Scanner View
- Create a new Swift file named
ScannerView.swift
. - Import the necessary frameworks and set up the UIViewControllerRepresentable to bridge UIKit with SwiftUI.
import SwiftUI
import AVFoundation
struct ScannerView: UIViewControllerRepresentable {
@Binding var scannedCode: String
func makeCoordinator() -> Coordinator {
Coordinator(scannedCode: $scannedCode)
}
func makeUIViewController(context: Context) -> UIViewController {
let viewController = ScannerViewController()
viewController.delegate = context.coordinator
return viewController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) { }
class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
@Binding var scannedCode: String
init(scannedCode: Binding<String>) {
_scannedCode = scannedCode
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
if let metadataObject = metadataObjects.first {
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
guard let stringValue = readableObject.stringValue else { return }
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
scannedCode = stringValue
}
}
}
}
Implementing the Scanner View Controller
- Create a new Swift file named
ScannerViewController.swift
. - Implement the barcode scanning logic using AVFoundation.
import UIKit
import AVFoundation
class ScannerViewController: UIViewController {
var captureSession: AVCaptureSession!
var previewLayer: AVCaptureVideoPreviewLayer!
var delegate: AVCaptureMetadataOutputObjectsDelegate?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
captureSession = AVCaptureSession()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed()
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(delegate, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417, .qr, .code128]
} else {
failed()
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = view.layer.bounds
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)
captureSession.startRunning()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if (captureSession?.isRunning == false) {
captureSession.startRunning()
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if (captureSession?.isRunning == true) {
captureSession.stopRunning()
}
}
func failed() {
let alertController = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
present(alertController, animated: true)
captureSession = nil
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}
Connecting Everything
- Update
ContentView.swift
to presentScannerView
when the button is tapped.
struct ContentView: View {
@State private var isShowingScanner = false
@State private var scannedCode = ""
var body: some View {
VStack {
Text("Scanned Barcode:")
.font(.headline)
Text(scannedCode)
.font(.largeTitle)
.padding()
Button(action: {
isShowingScanner = true
}) {
Text("Start Scanning")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.sheet(isPresented: $isShowingScanner) {
ScannerView(scannedCode: $scannedCode)
}
}
}
Testing the App
- Build and run the app on a physical device (as the simulator does not support camera usage).
- Tap the “Start Scanning” button and scan a barcode with the camera.
- The scanned barcode should appear on the screen.
In this tutorial, we’ve created a simple barcode scanner app using AVFoundation in Swift. This app includes:
- Setting up a new project with the necessary permissions.
- Designing the UI with SwiftUI.
- Implementing the barcode scanning functionality using AVFoundation.
- Bridging UIKit with SwiftUI to create a seamless user experience.
This basic app can be expanded with additional features like storing scanned barcodes, integrating with a database, or enhancing the UI. By leveraging the powerful AVFoundation framework and the simplicity of SwiftUI, you can build sophisticated barcode scanning applications for various use cases.