Skip to main content
Speed up MatrixScan Batch integration with Agent Skills

Install the official skill to help your coding agent (Claude Code, Codex, Cursor, etc.) integrate, debug, and customize MatrixScan Batch on iOS following Scandit's recommended patterns. More info →

Run this in a terminal in your project directory, then follow the instructions to select your coding agent.

npx skills add https://github.com/scandit/skills --skill matrixscan-batch-ios

Your coding agent loads the skill automatically based on your prompt; to invoke it explicitly, call /matrixscan-batch-ios followed by your task.

Get Started With SwiftUI

In this guide you will learn step-by-step how to add MatrixScan to your application using SwiftUI.

The general steps are:

  1. Create a UIViewController: Implement the MatrixScan logic following the main Get Started guide
  2. Create a SwiftUI wrapper: Use UIViewControllerRepresentable to integrate the UIViewController
  3. Use in your SwiftUI app: Add the SwiftUI view to your app's view hierarchy

The core MatrixScan implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide.

Create a UIViewController for MatrixScan

To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a UIViewController that handles the MatrixScan functionality. This follows the same implementation as described in the main Get Started guide.

Create a MatrixScanViewController class that implements all the steps from the UIKit guide:

import ScanditBarcodeCapture
import UIKit

class MatrixScanViewController: UIViewController {
private var context: DataCaptureContext!
private var camera: Camera?
private var barcodeBatch: BarcodeBatch!
private var captureView: DataCaptureView!
private var overlay: BarcodeBatchBasicOverlay!

override func viewDidLoad() {
super.viewDidLoad()
setupRecognition()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
barcodeBatch.isEnabled = true
camera?.switch(toDesiredState: .on)
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
barcodeBatch.isEnabled = false
camera?.switch(toDesiredState: .off)
}

func setupRecognition() {
// Follow the implementation from the Get Started guide:
// 1. Create data capture context
// 2. Configure the Barcode Batch Mode
// 3. Use the built-in camera
// 4. Visualize the scan process
// 5. Provide feedback
}
}

extension MatrixScanViewController: BarcodeBatchBasicOverlayDelegate {
func barcodeBatchBasicOverlay(_ overlay: BarcodeBatchBasicOverlay,
brushFor trackedBarcode: TrackedBarcode) -> Brush? {
// Return a custom Brush based on the tracked barcode.
}

func barcodeBatchBasicOverlay(_ overlay: BarcodeBatchBasicOverlay,
didTap trackedBarcode: TrackedBarcode) {
// Handle barcode tap
// See the main Get Started guide
}
}

Create a SwiftUI View using UIViewControllerRepresentable

Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app:

import SwiftUI
import UIKit

struct MatrixScanRepresentable: UIViewControllerRepresentable {
typealias UIViewControllerType = MatrixScanViewController

func makeUIViewController(context: Context) -> MatrixScanViewController {
return MatrixScanViewController()
}

func updateUIViewController(_ uiViewController: MatrixScanViewController, context: Context) {
// Update the view controller if needed
}
}

Use the SwiftUI View in Your App

Finally, use the MatrixScanRepresentable in your SwiftUI app:

import SwiftUI

@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
MatrixScanRepresentable()
}
}
}

Or within another SwiftUI view:

struct ContentView: View {
var body: some View {
NavigationView {
MatrixScanRepresentable()
.navigationTitle("MatrixScan")
}
}
}

Alternative: Using UIViewRepresentable

As an alternative to wrapping a UIViewController, you can implement the MatrixScan functionality directly using UIViewRepresentable. This approach uses a Coordinator to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates:

import ScanditBarcodeCapture
import SwiftUI

struct MatrixScanView: UIViewRepresentable {
let onBarcodeBatchUpdated: ([TrackedBarcode]) -> Void

func makeCoordinator() -> Coordinator {
Coordinator()
}

func makeUIView(context: Context) -> UIView {
let coordinator = context.coordinator
coordinator.onBarcodesUpdated = onBarcodeBatchUpdated

if let camera = Camera.default {
// Apply recommended camera settings
let cameraSettings = BarcodeBatch.recommendedCameraSettings
camera.apply(cameraSettings)

// Turn on the camera
coordinator.dataCaptureContext.setFrameSource(camera)
camera.switch(toDesiredState: .on)
coordinator.camera = camera
}

// Enable Barcode Batch
coordinator.barcodeBatch.isEnabled = true

// Create the capture view
let captureView = DataCaptureView(context: coordinator.dataCaptureContext, frame: .zero)
captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

// Create the overlay
coordinator.overlay = BarcodeBatchBasicOverlay(barcodeBatch: coordinator.barcodeBatch, view: captureView, style: .frame)

return captureView
}

func updateUIView(_ uiView: UIView, context: Context) {
context.coordinator.onBarcodesUpdated = onBarcodeBatchUpdated
}

static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) {
coordinator.barcodeBatch.isEnabled = false
coordinator.camera?.switch(toDesiredState: .off)
}

class Coordinator: NSObject, BarcodeBatchListener {
let dataCaptureContext: DataCaptureContext
let barcodeBatch: BarcodeBatch
var overlay: BarcodeBatchBasicOverlay?
var camera: Camera?
var onBarcodesUpdated: (([TrackedBarcode]) -> Void)?

override init() {
// Create the data capture context
DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --")
dataCaptureContext = DataCaptureContext.shared

// Configure barcode batch settings
let settings = BarcodeBatchSettings()
// ...

// Create barcode batch mode
barcodeBatch = BarcodeBatch(context: dataCaptureContext, settings: settings)

super.init()
barcodeBatch.addListener(self)
}

nonisolated func barcodeBatch(_ barcodeBatch: BarcodeBatch,
didUpdate session: BarcodeBatchSession,
frameData: FrameData) {
let trackedBarcodes = session.trackedBarcodes.values.map { $0 }
DispatchQueue.main.async {
self.onBarcodesUpdated?(trackedBarcodes)
}
}
}
}

You can then use this view directly in your SwiftUI app:

struct ContentView: View {
var body: some View {
NavigationView {
MatrixScanView { trackedBarcodes in
// Handle the tracked barcodes
}
.navigationTitle("MatrixScan")
}
}
}