Sample CodeiOS 15.0, iPadOS 15.0, Mac Catalyst 15.0, Xcode 16.0Reviewed 2026-07-21View on Apple Developer

AVCamBarcode: detecting barcodes and faces

At a glance

Item Summary
Purpose Detect machine-readable codes and faces in a configurable region, then draw interactive overlays.
App architecture Storyboard-driven UIKit app centered on one CameraViewController that owns the capture graph and coordinates specialized views.
Main patterns View Controller/MVC-style coordination, AVFoundation delegate callback, weak selection delegate, serial session and metadata queues.
Project style Flat target with one main controller, a preview view, a reusable generic selection controller, and storyboards.

Project structure

AVCamBarcode/
├── AppDelegate.swift
├── CameraViewController.swift
├── PreviewView.swift
├── ItemSelectionViewController.swift
├── Base.lproj/
│   ├── Main.storyboard
│   └── LaunchScreen.storyboard
└── Assets.xcassets/

Structure observations

  • Most capture, authorization, configuration, overlay, and UI coordination logic is colocated in CameraViewController.
  • PreviewView owns preview-layer and resizable-region rendering behavior.
  • ItemSelectionViewController<Item> is the only extracted reusable UI component and communicates completion through a protocol.

Overall architecture

Reference code

AVCamBarcode/CameraViewController.swift:257 — metadata-output wiring

if session.canAddOutput(metadataOutput) {
    session.addOutput(metadataOutput)
    metadataOutput.setMetadataObjectsDelegate(self, queue: metadataObjectsQueue)
    metadataOutput.metadataObjectTypes = metadataOutput.availableMetadataObjectTypes
}

Interpretation

The controller is both presentation coordinator and capture coordinator. Metadata arrives on a dedicated queue, is transformed into Core Animation overlays on the main queue, and is displayed over the preview layer. This is a compact UIKit sample rather than a separated service/view-model architecture.

Ownership and state

Ownership evidence

AVCamBarcode/CameraViewController.swift:173 — capture and UI references

private let session = AVCaptureSession()
private let sessionQueue = DispatchQueue(label: "session queue")
@IBOutlet private var previewView: PreviewView!
private let metadataOutput = AVCaptureMetadataOutput()
Owner Object or state Relationship Mutation authority
CameraViewController Session, metadata output, queues, overlays Creates and retains capture objects; receives storyboard view Controller methods, with session work dispatched to sessionQueue.
PreviewView Preview backing layer and region-of-interest shape/control layers Owns visual region state PreviewView; external callers propose a region through one method.
ItemSelectionViewController Selected items Owns selection state while presented Selection controller; final value returns through delegate.
ItemSelectionViewController Delegate Weak shared reference The presenting controller implements the callback; selector does not own it.

Class and protocol design

Type Responsibility Depends on
CameraViewController Configure capture, handle metadata, coordinate UI and overlays AVFoundation, PreviewView, selection controller, Safari services
PreviewView Host preview layer and provide draggable/resizable detection region UIKit, AVFoundation, Core Animation
ItemSelectionViewController<Item> Present single/multiple choice for any equatable raw-representable item UIKit, delegate protocol
ItemSelectionViewControllerDelegate Return generic selected values to the presenter Selection controller

Access control

Symbol Access Verified effect Likely rationale
Session, outputs, queues, outlets, and overlay helpers private Capture graph and UI wiring are usable only by CameraViewController Prevents unrelated files from mutating order-sensitive controller state.
PreviewView.regionOfInterest private(set) Controller/KVO can read it, but only PreviewView changes it Enforces clamping and redraw through setRegionOfInterestWithProposedRegionOfInterest.
Selection delegate weak, implicit internal Avoids a retain cycle while permitting the presenter callback Standard UIKit delegate ownership.
Main classes/protocol implicit internal Visible inside the app module, not exported The sample is an application target.

Reference code

AVCamBarcode/PreviewView.swift:137 — constrained region mutation

@objc private(set) dynamic var regionOfInterest = CGRect.null

func setRegionOfInterestWithProposedRegionOfInterest(
    _ proposedRegionOfInterest: CGRect
) {
    // Clamp, assign, and redraw.
}

No public, open, or fileprivate declaration appears in the Swift source.

Logic ownership and placement

Logic Owning type or file Placement rationale
Authorization/session lifecycle CameraViewController Coupled to view appearance and controller alerts.
Session mutation Controller private methods on sessionQueue AVFoundation session operations are serialized off-main.
Metadata-to-overlay transformation CameraViewController Requires both metadata output and preview-layer coordinates.
Region gesture/clamping/drawing PreviewView Geometry and layers remain inside the view that owns them.
Metadata-type/preset selection ItemSelectionViewController plus controller delegate Generic UI is separate; domain application stays with the camera controller.

Design patterns

Pattern Source evidence Purpose or tradeoff
UIKit View Controller/MVC-style coordinator AVCamBarcode/CameraViewController.swift:12 Centralizes a small sample, at the cost of a large multipurpose controller.
Delegate AVCamBarcode/CameraViewController.swift:12 and metadataOutput(_:didOutput:from:) at line 792 Receives asynchronous AVFoundation metadata.
Weak app delegate protocol AVCamBarcode/ItemSelectionViewController.swift:10 and line 16 Reuses selection UI without owning or knowing the presenting controller.
Thread confinement AVCamBarcode/CameraViewController.swift:177 and session-queue calls Keeps blocking/session mutation away from the main queue.
Backpressure/drop-latest behavior AVCamBarcode/CameraViewController.swift:792 and nonblocking semaphore wait Avoids accumulating stale overlay work.

Main application flow

Reference code

AVCamBarcode/CameraViewController.swift:792 — overlay callback

func metadataOutput(_ output: AVCaptureMetadataOutput,
                    didOutput metadataObjects: [AVMetadataObject],
                    from connection: AVCaptureConnection) {
    if metadataObjectsOverlayLayersDrawingSemaphore.wait(timeout: .now()) == .success {
        DispatchQueue.main.async {
            // Replace overlays, then signal.
        }
    }
}

Naming conventions

  • Types: UIKit role suffixes (ViewController, View) and framework-aligned MetadataObjectLayer.
  • Protocol: collaborator role with Delegate suffix.
  • Methods: lifecycle/configuration commands (configureSession, changeCamera) and delegate signatures dictated by AVFoundation/UIKit.
  • State: is... for Boolean status; ...Queue, ...Output, and ...Layer suffixes expose object roles.
  • Files: one primary UIKit type per Swift file; storyboard resources are grouped in Base.lproj.

Architecture takeaways

  • The source favors a conventional, controller-heavy UIKit sample over MVVM or service extraction.
  • Separate serial queues protect capture configuration and metadata delivery; Core Animation changes return to the main queue.
  • The preview view owns interactive geometry, while the controller owns detection semantics and overlay creation.
  • private(set) makes a view invariant explicit: outside code can observe the region but cannot bypass validation.
  • The generic selection controller is protocol-oriented at one narrow reuse point rather than across the whole app.

Source map

Source file Relevant symbols
AVCamBarcode/CameraViewController.swift CameraViewController, MetadataObjectLayer, capture and overlay flow
AVCamBarcode/PreviewView.swift PreviewView, preview layer, region-of-interest state
AVCamBarcode/ItemSelectionViewController.swift Generic selection controller and delegate protocol
AVCamBarcode/AppDelegate.swift UIKit application lifecycle entry