Sample CodeiOS, iPadOS, Mac CatalystReviewed 2026-07-21View on Apple Developer

Supporting Center Stage front camera in your iOS app

At a glance

Item Summary
Purpose Enable Center Stage for photos and videos on the iPhone front camera.
App architecture A Swift sample with the source-visible chain CenterStageFrontCamCameraViewCameraModelCaptureServiceAVFoundation APIs.
Main patterns Protocol-oriented abstraction, Delegate or data-source callbacks, Service object, Actor isolation
Project style 27 scanned source file(s) across Swift, organized around ranked entry, type, and file boundaries.
Execution model Source-visible boundaries: async declaration or closure, Task, @MainActor, Task closure isolated to MainActor, actor; none alone proves a background thread.
State/event model Source-visible mechanisms: @Observable, SwiftUI state property wrapper, NotificationCenter.
Key frameworks/packages SwiftUI, AVFoundation, os, Foundation, AppIntents; these are source dependencies, not architecture labels.

Project structure

Source bundle/
└── CenterStageFrontCamera/
    └── CenterStageFrontCam/
        ├── CenterStageFrontCam.swift
        ├── Model/
        │   └── DataTypes.swift
        ├── CameraView.swift
        ├── Preview Content/
        │   └── PreviewCameraModel.swift
        ├── Views/
        │   ├── CameraPreview.swift
        │   ├── Toolbars/
        │   │   └── MainToolbar/
        │   │       └── CaptureButton.swift
        │   ├── Controls/
        │   │   └── CaptureModeView.swift
        │   └── Overlays/
        │       ├── RecordingTimeView.swift
        │       └── StatusOverlayView.swift
        ├── CameraModel.swift
        ├── CaptureService.swift
        └── Support/
            └── ViewExtensions.swift

Structure observations

  • Architecturally prominent files are ranked from entry points and role-named declarations; resource-only paths are omitted.
  • Primary languages: Swift.
  • The verified tree contains 3 project/configuration file(s) and 52 source declaration(s).

Overall architecture

Reference code

CenterStageFrontCamera/CenterStageFrontCam/CenterStageFrontCam.swift:10 — architecture anchor

@main
/// The CenterStageFrontCam app's main entry point.
struct CenterStageFrontCam: App {

    @State private var camera = CameraModel()

    // An indication of the scene's operational state.
    @Environment(\.scenePhase) var scenePhase

    var body: some Scene {
        WindowGroup {
            CameraView(camera: camera)
                .preferredColorScheme(.dark)
                .statusBarHidden(true)
                .task {
                    // Start the capture pipeline.
                    await camera.start()
                }
            // Monitor the scene phase. Synchronize the persistent state when
            // the camera is running and the app becomes active.
                .onChange(of: scenePhase) { _, newPhase in
                    guard camera.status == .running, newPhase == .active else { return }
                    Task { @MainActor in
                        await camera.syncState()
                    }
                }
        }
    }
}

Interpretation

The arrows summarize the source-visible entry, role-named types or folders, and framework direction; when nodes come from structural folders, the sequence is a high-level interpretation rather than proof that every adjacent node calls the next. Ownership is claimed only where the next section cites a stored property or assignment. The diagram is intentionally limited to the dominant path into AVFoundation.

Ownership and state

Ownership evidence

CenterStageFrontCamera/CenterStageFrontCam/CenterStageFrontCam.swift:14 — stored dependency or nearest verified ownership anchor

struct CenterStageFrontCam: App {
    // ...
    @State private var camera = CameraModel()
    // ...
}
Owner Object or state Relationship Mutation authority
CenterStageFrontCam CameraModel (camera) owns wrapper-managed state Owning lexical scope
Photo Data (data) owns value state Initialized by the owner; the binding is immutable
Photo Bool (isProxy) owns value state Initialized by the owner; the binding is immutable
Photo URL (livePhotoMovieURL) owns value state Initialized by the owner; the binding is immutable

Composition arrows indicate a source-visible construction expression or locally owned value state; aggregation means the owner stores or receives a dependency without proving exclusive lifetime ownership.

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
Suspension boundary async declaration or closure The source declares or crosses an asynchronous boundary; it does not by itself establish background execution. CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:66
Task creation Task The source creates an unstructured task; surrounding context determines inherited actor isolation. CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:103
Main isolation @MainActor The cited annotation marks its attached declaration or closure as main-actor isolated. CenterStageFrontCamera/CenterStageFrontCam/CameraView.swift:18
Main isolation Task closure isolated to MainActor The cited operation explicitly enters a main-actor-isolated region. CenterStageFrontCamera/CenterStageFrontCam/Capture/PhotoCapture.swift:102
Actor isolation actor The cited type is actor-isolated; this does not select a background thread. CenterStageFrontCamera/CenterStageFrontCam/CaptureService.swift:15

@MainActor/MainActor.run, DispatchQueue.main, and RunLoop.main are reported as distinct isolation, queue, and event-loop mechanisms. A plain Task is kept separate from Task.detached; neither is labeled as a background thread.

Reference code

CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:66 — representative execution boundary

    func start() async {
        // ...
            status = .unauthorized
        // ...
    }

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
State propagation @Observable Observation macro publishes source-visible changes. CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:20
State propagation SwiftUI state property wrapper A SwiftUI property wrapper supplies or observes UI state. CenterStageFrontCamera/CenterStageFrontCam/CameraView.swift:21
State propagation NotificationCenter NotificationCenter distributes named process-local events. CenterStageFrontCamera/CenterStageFrontCam/CaptureService.swift:443
Source import SwiftUI The cited file imports this module; runtime use and architectural role are not inferred. CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:10
Source import AVFoundation The cited file imports this module; runtime use and architectural role are not inferred. CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:8
Source import os The cited file imports this module; runtime use and architectural role are not inferred. CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:9
Source import Foundation The cited file imports this module; runtime use and architectural role are not inferred. CenterStageFrontCamera/CenterStageFrontCam/CaptureService.swift:9
Source import AppIntents The cited file imports this module; runtime use and architectural role are not inferred. CenterStageFrontCamera/CenterStageFrontCam/Model/CameraState.swift:8

receive(on:) describes downstream delivery scheduling, while subscribe(on:) describes upstream subscription/request/cancel scheduling. An import Combine alone establishes neither behavior nor a Store, reducer, Redux, or other application architecture.

Class and protocol design

CenterStageFrontCamera/CenterStageFrontCam/Model/DataTypes.swift:171 — representative type boundary

protocol OutputService {
    associatedtype Output: AVCaptureOutput
    // ...
}
Type Responsibility Depends on or conforms to
OutputService Defines a capability or collaboration contract Concrete collaborators/imported frameworks
PlatformView Defines a capability or collaboration contract View
CameraView User-interface presentation and input forwarding Concrete collaborators/imported frameworks
PreviewCameraModel Feature data or observable state Camera
PreviewView User-interface presentation and input forwarding UIView, PreviewTarget
CameraModel Feature data or observable state Camera
CaptureService Framework-facing operations Concrete collaborators/imported frameworks
CaptureModeView User-interface presentation and input forwarding Concrete collaborators/imported frameworks
RecordingTimeView User-interface presentation and input forwarding PlatformView
StatusOverlayView User-interface presentation and input forwarding View

The source explicitly defines local protocol relationships: CameraModelCamera, MovieCaptureOutputService, PhotoCaptureOutputService, PreviewCameraModelCamera, PreviewSourceStubPreviewSource, PreviewViewPreviewTarget.

Access control

Symbol Access Verified effect Likely rationale
status (CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:24) private(set) Read access follows the declaration; writes remain in the private scope. Inference: allow observation while reserving invariant-changing writes for the owner.
captureActivity (CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:27) private(set) Read access follows the declaration; writes remain in the private scope. Inference: allow observation while reserving invariant-changing writes for the owner.
prefersMinimizedUI (CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:30) private(set) Read access follows the declaration; writes remain in the private scope. Inference: allow observation while reserving invariant-changing writes for the owner.
isSwitchingModes (CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:33) private(set) Read access follows the declaration; writes remain in the private scope. Inference: allow observation while reserving invariant-changing writes for the owner.

Reference code

CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:24 — representative boundary

@Observable
final class CameraModel: Camera {
    // ...
    private(set) var status = CameraStatus.unknown
    // ...
}

Swift declarations without a modifier are internal; explicit private, fileprivate, private(set), public, or open entries above are interpreted by language semantics. Objective-C/C samples instead rely on header and implementation boundaries, which are not equivalent to Swift lexical privacy.

Logic ownership and placement

Logic Owning type or file Placement rationale
Receives callback-driven events MovieCaptureDelegate, PhotoCaptureDelegate The source’s Delegate suffix makes this role explicit.
Feature data or observable state CameraModel, PreviewCameraModel The source’s Model suffix makes this role explicit.
Framework-facing operations CaptureService, OutputService The source’s Service suffix makes this role explicit.
User-interface presentation and input forwarding CameraView, CaptureModeView, PlatformView, PreviewView The source’s View suffix makes this role explicit.

Design patterns

Pattern Source evidence Purpose or tradeoff
Protocol-oriented abstraction CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:21 A local protocol and concrete conformance create an explicit capability boundary.
Delegate or data-source callbacks CenterStageFrontCamera/CenterStageFrontCam/Capture/MovieCapture.swift:85 Callback protocols invert event delivery back into the sample’s owner.
Service object CenterStageFrontCamera/CenterStageFrontCam/CaptureService.swift:15 A role-named service contains framework-facing operations.
Actor isolation CenterStageFrontCamera/CenterStageFrontCam/CaptureService.swift:15 A declared actor creates an explicit isolation boundary; its executor is not described as a background thread.

Main application flow

Reference code

CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift:209observeState()

    private func observeState() {
        Task {
            // Await new thumbnails that the media library generates when saving a file.
            for await thumbnail in mediaLibrary.thumbnails.compactMap({ $0 }) {
                self.thumbnail = thumbnail
            }
        }

        Task {
            // Await new capture activity values from the capture service.
            for await activity in captureService.captureActivityStream {
                if activity.willCapture {
                    // Flash the screen to indicate capture is starting.
                    flashScreen()
                } else {
                    // Forward the activity to the UI.
                    captureActivity = activity
                }
            }
        }

        Task {
            // Await updates to a person's interaction with the Camera Control HUD.
            for await isShowingFullscreenControls in captureService.isShowingFullscreenControlsStream {
                withAnimation {
                    // Prefer showing a minimized UI when capture controls enter a fullscreen appearance.
                    prefersMinimizedUI = isShowingFullscreenControls
                }
            }
        }
    }

Naming conventions

  • Types: Delegate: MovieCaptureDelegate, PhotoCaptureDelegate; Model: CameraModel, PreviewCameraModel; Service: CaptureService, OutputService; View: CameraView, CaptureModeView, PlatformView, PreviewView, RecordingTimeView.
  • Protocols: OutputService, PlatformView, PreviewSource, PreviewTarget, Camera.
  • Methods: updateConfiguration, setVideoRotationAngle, connect, start, capturePhoto, toggleRecording, focusAndExpose, capabilities.
  • Files: CenterStageFrontCamera/CenterStageFrontCam/CenterStageFrontCam.swift, CenterStageFrontCamera/CenterStageFrontCam/CameraView.swift, CenterStageFrontCamera/CenterStageFrontCam/Preview Content/PreviewCameraModel.swift, CenterStageFrontCamera/CenterStageFrontCam/Views/CameraPreview.swift, CenterStageFrontCamera/CenterStageFrontCam/Views/Toolbars/MainToolbar/CaptureButton.swift, CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift.

Architecture takeaways

  • CenterStageFrontCam is the main source-visible entry or composition anchor for this sample.
  • Framework work reaches SwiftUI, AVFoundation, AppIntents, PhotosUI through a deliberately small high-level chain; the detailed API graph remains inside the cited implementation files.
  • Stored-property evidence identifies lifecycle collaboration; it does not by itself prove exclusive object ownership.
  • Access-control conclusions separate verified language visibility from the likely design rationale.
  • Local protocol relationships provide an explicit substitution boundary.

Source map

Source file Relevant symbols
CenterStageFrontCamera/CenterStageFrontCam/CenterStageFrontCam.swift Cited implementation, CenterStageFrontCam
CenterStageFrontCamera/CenterStageFrontCam/Model/DataTypes.swift OutputService, CameraStatus, CaptureActivity, CaptureMode, Photo, Movie, PhotoFeatures, CaptureCapabilities, QualityPrioritization, CameraError
CenterStageFrontCamera/CenterStageFrontCam/CameraModel.swift Cited implementation, async declaration or closure, Task, @Observable, SwiftUI, AVFoundation, os, CameraModel
CenterStageFrontCamera/CenterStageFrontCam/Capture/MovieCapture.swift Cited implementation, MovieCapture, MovieCaptureDelegate
CenterStageFrontCamera/CenterStageFrontCam/CaptureService.swift CaptureService, actor, NotificationCenter, Foundation
CenterStageFrontCamera/CenterStageFrontCam/CameraView.swift @MainActor, SwiftUI state property wrapper, SwipeDirection, CameraView
CenterStageFrontCamera/CenterStageFrontCam/Capture/PhotoCapture.swift Task closure isolated to MainActor, PhotoCaptureError, PhotoCapture, PhotoCaptureDelegate
CenterStageFrontCamera/CenterStageFrontCam/Model/CameraState.swift AppIntents, CameraState, CodingKeys
CenterStageFrontCamera/CenterStageFrontCam/Preview Content/PreviewCameraModel.swift PreviewCameraModel, PreviewSourceStub
CenterStageFrontCamera/CenterStageFrontCam/Views/CameraPreview.swift CameraPreview, PreviewView, PreviewSource, PreviewTarget, DefaultPreviewSource
CenterStageFrontCamera/CenterStageFrontCam/Views/Toolbars/MainToolbar/CaptureButton.swift CaptureButton, PhotoCaptureButton, PhotoButtonStyle, MovieCaptureButton, NoFadeButtonStyle
CenterStageFrontCamera/CenterStageFrontCam/Support/ViewExtensions.swift PlatformView, AdaptiveToolbar, DefaultButtonStyle, Size
CenterStageFrontCamera/CenterStageFrontCam/Views/Controls/CaptureModeView.swift CaptureModeView
CenterStageFrontCamera/CenterStageFrontCam/Views/Overlays/RecordingTimeView.swift RecordingTimeView
CenterStageFrontCamera/CenterStageFrontCam/Views/Overlays/StatusOverlayView.swift StatusOverlayView
CenterStageFrontCamera/CenterStageFrontCam/Model/MediaLibrary.swift MediaLibrary, Error