Sample CodevisionOSReviewed 2026-07-21View on Apple Developer

Building local experiences with room tracking

At a glance

Item Summary
Purpose Use room tracking in visionOS to provide custom interactions with physical spaces.
App architecture ARKitRoomTrackingApp composes WindowGroup + ImmersiveSpace around ContentView; AppState coordinates ARKit provider updates and maps anchors into RealityKit content.
Main patterns SwiftUI scene composition, SwiftUI–RealityKit bridge, Explicit immersive-space lifecycle, Observable state owner, Provider session boundary, Async update consumer
Project style Code-rich sample with 5 scanned Swift file(s) and 813 Swift line(s); resources and generated assets are excluded from those counts.

Project structure

Source bundle/
└── ARKitRoomTracking/
    ├── ARKitRoomTrackingApp.swift  # ARKitRoomTrackingApp
    ├── ContentView.swift  # ContentView
    ├── WorldAndRoomView.swift  # WorldAndRoomView
    ├── AppState.swift  # AppState, VisualizationState, ErrorState
    └── Extensions.swift

Structure observations

  • The runtime boundary is WindowGroup + ImmersiveSpace; the pruned tree lists only files that explain lifecycle, state, or framework integration.
  • App code is split into role-named views, models, managers, providers, components, or systems.

Overall architecture

Reference code

ARKitRoomTracking/ARKitRoomTrackingApp.swift:15 — the app or executable entry declares the outer scene lifecycle.

struct ARKitRoomTrackingApp: App {
    // ...
}

The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It keeps scene ownership, shared state, RealityKit content, and framework-provider work at separate levels.

Ownership and state

Ownership evidence

ARKitRoomTracking/ARKitRoomTrackingApp.swift:17 — representative stored state or the nearest verified lifecycle anchor.

@main
@MainActor
struct ARKitRoomTrackingApp: App {
    // ...
    @State private var appState = AppState()
    // ...
}
Owner Object or state Relationship Mutation authority
ARKitRoomTrackingApp AppState as appState creates and retains Only the declaring scope writes
ContentView AppState as appState receives a shared/non-owning reference The upstream owner controls lifetime; this scope may invoke its mutable API
ErrorState ARKitSession as session creates and retains Only the declaring scope writes
ContentView ScenePhase as scenePhase receives a shared/non-owning reference The upstream owner controls lifetime; this scope may invoke its mutable API

Ownership here is deliberately narrow: @Environment and weak references are shared links, initialized @State or stored services are lifecycle ownership, and a RealityView content closure owns additions to its entity graph without making the SwiftUI view a reference-type owner.

Class and protocol design

Type Responsibility Depends on or conforms to
ARKitRoomTrackingApp (ARKitRoomTracking/ARKitRoomTrackingApp.swift:15) Declares app scenes and top-level dependency lifetime. App
ContentView (ARKitRoomTracking/ContentView.swift:13) Presents UI and forwards gestures or lifecycle events. View
AppState (ARKitRoomTracking/AppState.swift:14) Owns observable feature state and domain transitions. Concrete framework collaborators
WorldAndRoomView (ARKitRoomTracking/WorldAndRoomView.swift:15) Presents UI and forwards gestures or lifecycle events. View

The source defines no local substitution protocol in the reviewed boundary. Its protocol use is framework-facing (App, View, RealityKit/ARKit protocols, or platform adapters), so this document does not label the whole app protocol-oriented.

Access control

Symbol Access Verified effect Likely rationale
@State private var appState = AppState() (ARKitRoomTracking/ARKitRoomTrackingApp.swift:17) private Use is restricted to the declaration and same-file extensions permitted by Swift. Inference: Hide implementation details and lifecycle-sensitive state.

No reviewed declaration uses fileprivate, private(set), public, open; unmodified Swift declarations are internal.

Reference code

ARKitRoomTracking/ARKitRoomTrackingApp.swift:17 — representative visibility boundary.

@main
@MainActor
struct ARKitRoomTrackingApp: App {
    // ...
}

Logic ownership and placement

Logic Owning type or file Placement rationale
Scene declaration and dependency lifetime ARKitRoomTrackingApp The App/entry boundary determines window, volume, and immersive-space lifetime.
Presentation, attachments, and gestures ContentView SwiftUI view code forwards user intent and RealityView lifecycle events.
Shared feature state and commands AppState A role-named owner prevents sibling views from duplicating transitions.
Tracking authorization and update streams ARKitRoomTracking/ContentView.swift:110 Provider lifetime and async updates remain outside render-only view code.

Design patterns

Pattern Source evidence Purpose or tradeoff
SwiftUI scene composition ARKitRoomTracking/ARKitRoomTrackingApp.swift:15 Keeps windows, volumes, and immersive-space lifecycle visible at the app boundary.
SwiftUI–RealityKit bridge ARKitRoomTracking/WorldAndRoomView.swift:40 Builds and updates a RealityKit entity graph from SwiftUI lifecycle closures.
Explicit immersive-space lifecycle ARKitRoomTracking/ARKitRoomTrackingApp.swift:25 Makes immersive presentation a scene transition rather than hidden global state.
Observable state owner ARKitRoomTracking/AppState.swift:14 Shares feature state across multiple views without moving framework resources into view values.
Provider session boundary ARKitRoomTracking/AppState.swift:39 Owns provider lifetime separately from the SwiftUI view tree.
Async update consumer ARKitRoomTracking/AppState.swift:301 Consumes provider or event streams in cancellable structured tasks.

Naming conventions

  • Role suffixes are evidence, not decoration: App: ARKitRoomTrackingApp; View: ContentView, WorldAndRoomView.
  • Protocols: no app-defined protocol in the reviewed source.
  • Commands use verb-led methods: createPreviewSphere, run, setupContentEntity, areAllDataProvidersAuthorized, runSession, isSphereInCurrentRoom, updateSphereState, getNearestWall.
  • Files generally match their primary type; Views, Models, Managers, Providers, Components, Systems, and Packages folders describe architectural roles where present.

Architecture takeaways

  • Treat ARKitRoomTrackingApp as the owner of scene declarations, not as the owner of every RealityKit entity created later.
  • Keep view-local interaction in SwiftUI, but move provider sessions, playback resources, shared game state, or transport state into a stable owner when their lifetime exceeds one render pass.
  • Run ARKit providers for the scene lifetime and consume their asynchronous updates in cancellable tasks; map anchors to entities at the boundary.
  • Model immersive-space open, transition, and close states explicitly so windows and immersive content cannot drift apart.

Source map

Source file Relevant symbols
ARKitRoomTracking/ARKitRoomTrackingApp.swift:15 ARKitRoomTrackingApp
ARKitRoomTracking/ContentView.swift:13 ContentView
ARKitRoomTracking/WorldAndRoomView.swift:15 WorldAndRoomView
ARKitRoomTracking/AppState.swift:14 AppState, VisualizationState, ErrorState
ARKitRoomTracking/Extensions.swift:1 Feature implementation