Sample CodeiOS, iPadOS, Mac CatalystReviewed 2026-11-01View on Apple Developer

Building a responsive camera app that launches quickly

At a glance

Item Summary
Purpose Show the camera preview sooner by deferring capture-output startup and holding back noncritical controls until the session is running.
App architecture An AVCam-based project (AVCam.xcodeproj) with three targets. A @MainActor CameraModel drives a CaptureService actor that configures the session with deferred start. SwiftUI controls are revealed when CameraModel.status becomes .running.
Main patterns Actor isolation (custom serial executor), protocol-oriented abstraction (Camera, OutputService, PreviewSource/PreviewTarget), delegate callbacks bridged to async, and @Published state consumed as async sequences.
Project style Swift sources grouped by role (Capture/, Model/, Views/, Support/). The launch-specific code is a small number of edits spread across CaptureService, PhotoCapture, MovieCapture, one View extension, and four control views.
Execution model CameraModel is @MainActor. CaptureService is an actor whose executor is the serial DispatchSerialQueue sessionQueue, so setUpSession() and the blocking startRunning() run as jobs on that queue. The main actor is suspended at await, not blocked.
State/event model @Observable model state (status) gates control visibility through a hidden(until:) modifier. Actor @Published properties are read through .values. scenePhase drives a preview cover.
Key frameworks/packages AVFoundation, SwiftUI, Combine, Photos, LockedCameraCapture, ExtensionKit, AppIntents, WidgetKit. The project declares no Swift package.

Platform boundary: the DocC record lists iOS, iPadOS, and Mac Catalyst. In the downloaded project, every target sets SUPPORTS_MACCATALYST = NO with SDKROOT = iphoneos (AVCam.xcodeproj/project.pbxproj:945), and the deployment target is iOS 26.0 (AVCam.xcodeproj/project.pbxproj:936), while the DocC record lists 27.0. The bundled README.md is the generic AVCam overview (README.md:1), so this analysis relies on the source code and its comments for the launch-specific behavior.

Project structure

AVCam.xcodeproj/                     (3 targets, no Swift packages)
AVCam/                               app sources (also compiled into the capture extension)
├── AVCamApp.swift                   @main App; .task { await camera.start() }
├── CameraModel.swift                @MainActor @Observable; sets status = .running
├── CaptureService.swift             actor; deferred-start configuration in setUpSession()
├── Capture/
│   ├── PhotoCapture.swift           enables responsive capture on the photo output
│   └── MovieCapture.swift           configures the video connection before recording
├── Model/                           Camera protocol, CameraState, DataTypes, MediaLibrary actor
├── Support/ViewExtensions.swift     View.hidden(until:)
└── Views/
    ├── PreviewContainer.swift       background cover keyed to scenePhase
    ├── CameraUI.swift               window size from onGeometryChange
    ├── Controls/CaptureModeView.swift
    └── Toolbars/                    MainToolbar, FeatureToolbar, CaptureButton
AVCamCaptureExtension/               LockedCameraCaptureExtension entry
AVCamControlCenterExtension/         ControlWidget bundle

Structure observations

  • The project has three native targets: AVCam (application), AVCamCaptureExtension (ExtensionKit extension), and AVCamControlCenterExtension (app extension) (AVCam.xcodeproj/project.pbxproj:445). The capture extension compiles the shared AVCam sources, including CaptureService.swift and CameraModel.swift (AVCam.xcodeproj/project.pbxproj:525, AVCam.xcodeproj/project.pbxproj:542). It creates its own CameraModel and starts it the same way the app does (AVCamCaptureExtension/AVCamCaptureExtension.swift:17, AVCamCaptureExtension/AVCamCaptureExtension.swift:25).
  • The launch work splits into two layers that never call each other directly. The capture layer (CaptureService.setUpSession()) opts outputs into deferred start. The view layer gates controls on camera.status == .running. The only link between them is CameraModel.status.
  • The deferral is implemented once, as a View extension (AVCam/Support/ViewExtensions.swift:64), and applied by the views that should wait (AVCam/Views/Toolbars/MainToolbar/MainToolbar.swift:25, AVCam/Views/Controls/CaptureModeView.swift:44, AVCam/Views/Toolbars/FeatureToolbar/FeatureToolbar.swift:36).
  • The project still includes the AVCam rotation coordinator, which setUpSession() creates after it adds the outputs (AVCam/CaptureService.swift:158).

Overall architecture

Reference code

AVCam/CaptureService.swift:137 — deferred-start configuration in setUpSession()

    private func setUpSession() throws {
        // ...
        do {
            // ...
            // Deferred start brings up the preview first, and prepares the capture outputs a moment
            // later. An app that links the iOS 26 SDK gets this behavior by default; these
            // assignments show the properties that control it.
            captureSession.automaticallyRunsDeferredStart = true

            // Add the photo capture output as the default output type.
            photoCapture.output.isDeferredStartEnabled = photoCapture.output.isDeferredStartSupported
            try addOutput(photoCapture.output)
            // If the capture mode is set to `video`, add a movie capture output.
            if captureMode == .video {
                // Add the movie output as the default output type.
                movieCapture.output.isDeferredStartEnabled = movieCapture.output.isDeferredStartSupported
                try addOutput(movieCapture.output)
                setHDRVideoEnabled(isHDRVideoEnabled)
            }
            // ...
        } catch {
            throw CameraError.setupFailed
        }
    }

Interpretation

Observed: the sample uses the automatic mode. It sets automaticallyRunsDeferredStart = true and enables isDeferredStartEnabled on each output only when isDeferredStartSupported is true. The source does not call runDeferredStartWhenNeeded or set a deferred-start delegate, so there is no manual trigger to analyze. The source comment notes that these assignments match the default for an app that links the iOS 26 SDK. They make the opt-in visible rather than changing behavior.

Inference: the architecture needs very little extra structure for fast launch because AVCam already isolates session work in an actor with its own queue. The launch-specific edits add configuration flags in the actor and a visibility rule in the views.

Ownership and state

Ownership evidence

AVCam/CameraModel.swift:68 — the single writer of the launch gate

    func start() async {
        // Verify that the person authorizes the app to use device cameras and microphones.
        guard await captureService.isAuthorized else {
            status = .unauthorized
            return
        }
        do {
            // Synchronize the state of the model with the persistent state.
            await syncState()
            // Start the capture service to start the flow of data.
            try await captureService.start(with: cameraState)
            observeState()
            status = .running
        } catch {
            logger.error("Failed to start capture service. \(error)")
            status = .failed
        }
    }
Owner Object or state Relationship Mutation authority
AVCamApp CameraModel Creates it in @State private var camera (AVCam/AVCamApp.swift:16) CameraModel
CameraModel status private(set) var status (AVCam/CameraModel.swift:24). It is set to .running only after captureService.start(with:) returns (AVCam/CameraModel.swift:80). CameraModel, on the main actor
CameraModel CaptureService, MediaLibrary Creates and retains them in private let (AVCam/CameraModel.swift:54, AVCam/CameraModel.swift:57) Each actor changes its own state
CaptureService AVCaptureSession, PhotoCapture, MovieCapture Creates them in private let (AVCam/CaptureService.swift:31, AVCam/CaptureService.swift:34) Only the actor
CaptureService Deferred-start flags on the session and outputs Assigned once in setUpSession() (AVCam/CaptureService.swift:140) Only the actor
Control views Visibility Read camera.status and apply hidden(until:). They store no launch state of their own. (AVCam/Views/Toolbars/MainToolbar/MainToolbar.swift:35) None; derived from model state
PreviewContainer coverOpacity @State private var (AVCam/Views/PreviewContainer.swift:31), changed in updateCoverOpacity PreviewContainer
CameraUI windowSize @State private var (AVCam/Views/CameraUI.swift:21), written by onGeometryChange CameraUI

Observed: launch readiness is not a separate flag. Views reuse the existing CameraStatus value, and StatusOverlayView already renders the unauthorized, failed, and interrupted cases (AVCam/Views/Overlays/StatusOverlayView.swift:14). Controls stay at zero opacity in every state except .running.

Concurrency, scheduling, and thread safety

Evidence limit: actor isolation, async/await, or Task creation does not by itself prove background-thread execution; Sendable conformance alone does not prove thread-safe mutation.

Concern Source mechanism Verified placement or handoff Evidence
Start-up task .task { await camera.start() } SwiftUI creates the start task and ties it to the root view’s lifetime. The method it awaits, CameraModel.start(), is main-actor isolated. AVCam/AVCamApp.swift:25
Main-actor isolation @MainActor final class CameraModel status, and the decision to set it to .running, are main-actor state AVCam/CameraModel.swift:19
Actor executor actor CaptureService with unownedExecutor returning sessionQueue.asUnownedSerialExecutor() start(with:), setUpSession(), and captureSession.startRunning() run as jobs on the serial queue sessionQueue AVCam/CaptureService.swift:68, AVCam/CaptureService.swift:71, AVCam/CaptureService.swift:108
Ordered launch steps Sequential awaits in CameraModel.start() Authorization, then syncState() (which awaits CameraState.current), then captureService.start(with:), then observeState(), then status = .running AVCam/CameraModel.swift:70, AVCam/CameraModel.swift:76, AVCam/CameraModel.swift:78
Preview attachment nonisolated func setSession(_:) creating Task { @MainActor in previewLayer.session = session } The preview layer is attached on the main actor, independently of the actor’s setup job AVCam/Views/CameraPreview.swift:63, AVCam/Views/CameraPreview.swift:66
Plain Task {} inheriting the main actor Four for await loops in observeState() Started after the session runs. The loops are not stored, so nothing cancels them. AVCam/CameraModel.swift:198
Plain Task {} inheriting the actor Notification loops in observeNotifications(); monitorSystemPreferredCamera() Each body mutates isolated state without await, so it inherits CaptureService isolation. They are unretained. AVCam/CaptureService.swift:359, AVCam/CaptureService.swift:557
Retained, cancellable task subjectAreaChangeTask?.cancel(), then a new Task The only stored actor task AVCam/CaptureService.swift:443, AVCam/CaptureService.swift:452
Caller-isolation inheritance monitorProgress(of:isolation: isolated (any Actor)? = #isolation) The photo-progress task captures the calling actor’s isolation AVCam/Capture/PhotoCapture.swift:89
Shutter tap Task { await camera.capturePhoto() } in CaptureButton Created from a main-actor view action. The button is never hidden, so a tap can arrive before deferred start finishes. AVCam/Views/Toolbars/MainToolbar/CaptureButton.swift:37
Main run-loop timer Timer.publish(every:on: .main, in: .common) Recording-duration ticks. The stored cancellable is cancelled on stop. AVCam/Capture/MovieCapture.swift:84, AVCam/Capture/MovieCapture.swift:96
Compiler checking level SWIFT_STRICT_CONCURRENCY = minimal, @preconcurrency import AVFoundation Concurrency checking is minimal, so the compiler does not fully verify these crossings AVCam.xcodeproj/project.pbxproj:949, AVCam/CaptureService.swift:9

Reference code

AVCam/CaptureService.swift:99 — session start on the actor’s queue

    func start(with state: CameraState) async throws {
        // Set initial operating state.
        captureMode = state.captureMode
        isHDRVideoEnabled = state.isVideoHDREnabled
        
        // Exit early if not authorized or the session is already running.
        guard await isAuthorized, !captureSession.isRunning else { return }
        // Configure the session and start it.
        try setUpSession()
        captureSession.startRunning()
    }

Interpretation: the README explains that configuring and starting a session are blocking operations, and that the actor keeps them off the main thread (README.md:13). The custom executor (AVCam/CaptureService.swift:71) is the code that makes this true. While startRunning() blocks sessionQueue, CameraModel.start() is suspended at await, so the main actor can keep rendering the preview container and the visible shutter. Deferred start then shortens the blocking call itself by postponing output preparation (per the source comment at AVCam/CaptureService.swift:137).

Not established by source: how long deferred start takes, or exactly when outputs become ready. The app has no deferred-start callback and does not observe readiness. Its only signal is CameraModel.status, which becomes .running once startRunning() returns.

State propagation, frameworks, and dependencies

Evidence limit: an import proves a source-level compilation dependency at the cited line; it does not prove runtime use, architectural adoption, or whether a Swift package is a direct application dependency.

Category Mechanism or module Verified role Evidence
Launch gate @Observable CameraModel.status read by hidden(until: camera.status == .running) Controls fade in over 0.3 s once status becomes .running AVCam/CameraModel.swift:20, AVCam/Support/ViewExtensions.swift:65
Scene lifecycle @Environment(\.scenePhase) with .onChange(of: scenePhase, updateCoverOpacity) Covers the preview in .background and fades the cover out in .active AVCam/Views/PreviewContainer.swift:27, AVCam/Views/PreviewContainer.swift:67, AVCam/Views/PreviewContainer.swift:81
Layout measurement onGeometryChange(for: CGSize.self) into windowSize bottomPadding uses the measured window instead of a screen-wide constant AVCam/Views/CameraUI.swift:33, AVCam/Views/CameraUI.swift:89
Actor-to-model state @Published private(set) on the actor, read through .values Capture activity, capabilities, and the fullscreen-controls flag reach the model AVCam/CaptureService.swift:17, AVCam/CameraModel.swift:207
Output-to-actor state Publishers.Merge(...).assign(to: &$captureActivity) Combines photo and movie activity AVCam/CaptureService.swift:540
Framework import SwiftUI, Combine only, in CameraModel.swift The model file does not import AVFoundation AVCam/CameraModel.swift:8, AVCam/CameraModel.swift:9
Framework import @preconcurrency import AVFoundation Capture and preview code AVCam/CaptureService.swift:9, AVCam/Views/CameraPreview.swift:9
Framework import ExtensionKit, LockedCameraCapture Capture-extension entry point AVCamCaptureExtension/AVCamCaptureExtension.swift:8, AVCamCaptureExtension/AVCamCaptureExtension.swift:10
Package declaration None The project file declares no Swift package dependency AVCam.xcodeproj/project.pbxproj:445

Combine scheduling: the source never calls receive(on:) or subscribe(on:). Delivery to the model goes through .values inside main-actor tasks.

Class and protocol design

Reference code

AVCam/Capture/MovieCapture.swift:100 — connection setup moved out of the record path

    func updateConfiguration(for device: AVCaptureDevice) {
        // The app supports HDR video capture if the active format supports it.
        isHDRSupported = device.activeFormat10BitVariant != nil

        // The output has a video connection only while the session contains it, which is the
        // case in video capture mode. Adding the output creates a new connection, so the service
        // configures it here rather than when recording starts.
        guard let connection = movieOutput.connection(with: .video) else { return }

        // Configure the connection for HEVC capture.
        if movieOutput.availableVideoCodecTypes.contains(.hevc) {
            movieOutput.setOutputSettings([AVVideoCodecKey: AVVideoCodecType.hevc], for: connection)
        }
        // ...
        if connection.isVideoStabilizationSupported {
            connection.preferredVideoStabilizationMode = .auto
        }
    }
Type Responsibility Depends on
CaptureService (actor) Session setup with deferred start, device and mode changes, output configuration fan-out AVCaptureSession, OutputService conformers
CameraModel (@MainActor class) Runs the ordered launch sequence and publishes status CaptureService, MediaLibrary, CameraState
Camera (protocol) View-facing contract that includes status Value types in DataTypes.swift
PhotoCapture Photo output; enables responsive capture, fast capture prioritization, and auto-deferred delivery when supported OutputService
MovieCapture Movie output; prepares the video connection in updateConfiguration OutputService
View.hidden(until:) One reusable launch-visibility rule SwiftUI opacity, animation

Observed: OutputService.updateConfiguration(for:) is the hook CaptureService calls for every output whenever the configuration changes (AVCam/CaptureService.swift:527). This tree uses that hook to move HEVC and stabilization setup ahead of recording. The source comment gives the reason: it avoids “changing the framing at the moment recording begins” (AVCam/Capture/MovieCapture.swift:116).

Access control

Symbol Access Verified effect Likely rationale
CameraModel.status (AVCam/CameraModel.swift:24) private(set) Views can read the launch gate but cannot set it Inference: only the start sequence can declare the camera running.
CameraModel.captureService (AVCam/CameraModel.swift:57) private Views cannot call the actor or toggle deferred start Inference: launch tuning stays in the capture layer.
CaptureService.setUpSession() (AVCam/CaptureService.swift:113) private Deferred-start configuration is reachable only through start(with:) Inference: the flags are applied once, before startRunning().
CaptureService.previewSource (AVCam/CaptureService.swift:28) implicit internal, nonisolated let Readable synchronously from main-actor views Inference: the preview can attach without waiting for an actor hop.
PreviewContainer.coverOpacity, CameraUI.windowSize (AVCam/Views/PreviewContainer.swift:31, AVCam/Views/CameraUI.swift:21) @State private View-local presentation state Inference: launch and resume polish is view-owned and kept out of the model.
View.hidden(until:) (AVCam/Support/ViewExtensions.swift:64) implicit internal Available to any view in the module Inference: one shared modifier instead of a copied if in each control.

Reference code

AVCam/Support/ViewExtensions.swift:59 — the shared deferral modifier

extension View {
    /// Hides this view until the capture session is running.
    ///
    /// The app applies this to its controls so that it doesn't show UI until it's
    /// functional, and so the preview is the first thing to appear at launch.
    func hidden(until isRunning: Bool) -> some View {
        opacity(isRunning ? 1 : 0)
            .animation(.easeIn(duration: 0.3), value: isRunning)
    }
}

Observed: the modifier uses opacity rather than conditional inclusion, so the hidden controls stay in the view hierarchy and keep their layout space before launch completes. Most declarations use Swift’s implicit internal. The private and private(set) modifiers above are the meaningful boundaries.

Logic ownership and placement

Logic Owning type or file Placement rationale
Opt outputs into deferred start CaptureService.setUpSession() Runs on the actor’s queue, before any output is added (AVCam/CaptureService.swift:143).
Decide when the camera is running CameraModel.start() The only writer of status, after the actor returns (AVCam/CameraModel.swift:80).
Hide noncritical controls Each control view, through hidden(until:) Thumbnail, camera switch, mode picker, and feature toolbar (AVCam/Views/Toolbars/MainToolbar/MainToolbar.swift:25).
Keep the shutter available MainToolbar CaptureButton gets no gate. The source comment relies on responsive capture to honor early taps (AVCam/Views/Toolbars/MainToolbar/MainToolbar.swift:27). That capability is enabled in PhotoCapture.updateConfiguration (AVCam/Capture/PhotoCapture.swift:124).
Avoid a stale frame on resume PreviewContainer.updateCoverOpacity A view concern keyed to scenePhase (AVCam/Views/PreviewContainer.swift:81).
Prepare recording ahead of time MovieCapture.updateConfiguration Configuration-time hook instead of the record path (AVCam/Capture/MovieCapture.swift:107).

Design patterns

Pattern Source evidence Purpose or tradeoff
Actor isolation actor CaptureService with a sessionQueue executor (AVCam/CaptureService.swift:14, AVCam/CaptureService.swift:71); actor MediaLibrary (AVCam/Model/MediaLibrary.swift:13) Keeps the blocking session setup and start off the main actor, which deferred start depends on for a responsive launch
Protocol-oriented abstraction Camera (AVCam/Model/Camera.swift:15) with CameraModel and PreviewCameraModel; OutputService (AVCam/Model/DataTypes.swift:143); PreviewSource (AVCam/Views/CameraPreview.swift:79) Views depend on Camera.status, not on capture types. Output preparation fans out through one protocol hook.
Delegate or data-source callbacks PhotoCaptureDelegate, MovieCaptureDelegate, CaptureControlsDelegate (AVCam/CaptureService.swift:582) AVFoundation callbacks are bridged into continuations, streams, or @Published values
Publisher-backed observable state @Published private(set) on the actor and output wrappers, consumed through .values (AVCam/CameraModel.swift:207) The capture layer publishes, and the main-actor model iterates. Only the owner writes.

Removed from the draft: “Service object”, which came from the Service suffix and adds nothing beyond the verified actor and protocol boundaries, and “SwiftUI environment injection”. The views read system environment values (scenePhase, size classes), but the app does not inject its own dependencies through the environment: CameraModel is passed as an initializer argument (AVCam/AVCamApp.swift:23). No MVVM or Coordinator label is claimed.

Main application flow

Reference code

AVCam/Views/Toolbars/MainToolbar/MainToolbar.swift:19 — gated controls around an ungated shutter

    var body: some View {
        HStack {
            ThumbnailButton(camera: camera)
                // Hide the thumbnail button when a person interacts with capture controls.
                .opacity(camera.prefersMinimizedUI ? 0 : 1)
                // Hide it until the capture session runs, using a custom modifier.
                .hidden(until: camera.status == .running)
            Spacer()
            // The capture button stays visible. A capture that arrives before deferred start
            // finishes is still honored, because the photo output enables responsive capture.
            CaptureButton(camera: camera)
            Spacer()
            SwitchCameraButton(camera: camera)
                // Hide the camera selection when a person interacts with capture controls.
                .opacity(camera.prefersMinimizedUI ? 0 : 1)
                // Hide it until the capture session runs, using a custom modifier.
                .hidden(until: camera.status == .running)
        }
        // ...
    }

Observed: the order in the diagram comes from CameraModel.start() and CaptureService.start(with:), which are excerpted in full under Ownership evidence and in the concurrency section’s reference code. Inference: since syncState() awaits the capture intent’s stored context before the session starts, that fetch is on the launch path. A team optimizing launch further could measure it, but the source makes no claim about its cost.

Naming conventions

  • Types: the same AVCam role nouns as the base sample: CaptureService (actor), CameraModel, PhotoCapture/MovieCapture output wrappers, AVFoundation adopters ending in Delegate, PreviewContainer, CameraUI, toolbar and button views.
  • Protocols: Camera for the view-facing capability. OutputService, PreviewSource, and PreviewTarget for collaborator roles.
  • Methods: the launch addition reads as a sentence at the call site: .hidden(until: camera.status == .running). Lifecycle verbs are start, setUpSession, syncState, observeState, and updateConfiguration(for:). View handlers follow update<Thing>(_:_:), matching the onChange signature (updateBlurRadius, updateCoverOpacity). The AVFoundation flags use framework names (isDeferredStartEnabled, automaticallyRunsDeferredStart). App Booleans use is…/prefers…/should….
  • Files and extensions: one primary type per file. The generic modifier is in Support/ViewExtensions.swift, not in a launch-specific file, so launch behavior appears as edits to existing types rather than a new module.

Architecture takeaways

  • Fast launch here is two independent mechanisms joined by one value. The capture actor defers output preparation, the views defer noncritical controls, and CameraModel.status is the only signal between them.
  • The actor’s custom serial executor is what keeps the blocking startRunning() off the main actor (AVCam/CaptureService.swift:71). Deferred start shortens that call but does not remove the need for the actor.
  • Hide with opacity, not conditional view creation, when layout must stay stable. Keep the primary action (the shutter) available and rely on a framework capability (responsive capture) to accept early input.
  • Move expensive or framing-changing setup from the action path to the configuration path. MovieCapture.updateConfiguration prepares the video connection before the person presses record.
  • Task lifetimes are mostly implicit. The start-up task belongs to SwiftUI’s .task, the observation loops are unretained, and only subjectAreaChangeTask is stored and cancelled.

Source map

Source file Relevant symbols
AVCam/CaptureService.swift CaptureService, sessionQueue, unownedExecutor, start(with:), setUpSession(), automaticallyRunsDeferredStart, isDeferredStartEnabled, CaptureControlsDelegate
AVCam/CameraModel.swift CameraModel, start(), status, observeState()
AVCam/Support/ViewExtensions.swift View.hidden(until:)
AVCam/Views/Toolbars/MainToolbar/MainToolbar.swift MainToolbar
AVCam/Views/Toolbars/MainToolbar/CaptureButton.swift CaptureButton
AVCam/Views/Controls/CaptureModeView.swift CaptureModeView
AVCam/Views/Toolbars/FeatureToolbar/FeatureToolbar.swift FeaturesToolbar
AVCam/Views/PreviewContainer.swift PreviewContainer, updateCoverOpacity(_:_:)
AVCam/Views/CameraUI.swift CameraUI, windowSize, bottomPadding
AVCam/Views/CameraPreview.swift PreviewView.setSession(_:), PreviewSource
AVCam/Views/Overlays/StatusOverlayView.swift StatusOverlayView
AVCam/Capture/PhotoCapture.swift PhotoCapture, updateConfiguration(for:), monitorProgress(of:isolation:)
AVCam/Capture/MovieCapture.swift MovieCapture, updateConfiguration(for:)
AVCam/Model/Camera.swift Camera
AVCam/Model/DataTypes.swift OutputService, CameraStatus
AVCam/Model/MediaLibrary.swift MediaLibrary
AVCam/AVCamApp.swift AVCamApp
AVCamCaptureExtension/AVCamCaptureExtension.swift AVCamCaptureExtension
AVCam.xcodeproj/project.pbxproj Targets, Sources phases, SWIFT_STRICT_CONCURRENCY, SUPPORTS_MACCATALYST
README.md Generic AVCam overview and actor rationale