Sample CodemacOSReviewed 2026-07-21View on Apple Developer

Building an object reconstruction app

At a glance

Item Summary
Purpose Reconstruct objects from user-selected input images by using photogrammetry.
App architecture ObjectCaptureReconstructionApp presents ContentView, which owns AppDataModel; the views collect input/output choices while the model creates a photogrammetry session, submits requests, and translates asynchronous outputs into reconstruction progress.
Main patterns SwiftUI scene composition, UI–RealityKit bridge, Observable state owner, Session owner boundary, Async update consumer, Photogrammetry request pipeline
Project style Code-rich sample with 30 scanned Swift file(s) and 1559 implementation line(s).

Project structure

Source bundle/
└── ObjectCaptureReconstruction/
    ├── AppDataModel.swift  # AppDataModel, State, DetailLevelOptionsUnderAdvancedMenu
    ├── ObjectCaptureReconstructionApp.swift  # ObjectCaptureReconstructionApp
    ├── Settings/
    │   ├── ReconstructionOptions/
    │   │   ├── MaskingView.swift  # MaskingView, MaskingOption
    │   │   └── IgnoreBoundingBoxView.swift  # IgnoreBoundingBoxView
    │   └── FolderOptions/
    │       └── FolderOptionsView.swift  # FolderOptionsView
    ├── ContentView.swift  # ContentView
    └── Processing/
        └── BottomBarView.swift  # BottomBarView

Structure observations

  • The runtime boundary is Window; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
  • The source is Swift; role-named types and feature folders separate the major responsibilities.

Overall architecture

Reference code

ObjectCaptureReconstruction/ObjectCaptureReconstructionApp.swift:11 — executable or app-lifecycle anchor.

struct ObjectCaptureReconstructionApp: App {
    // ...
}

The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It separates lifecycle, presentation, stable state, framework/session work, and the RealityKit entity graph.

Ownership and state

Ownership evidence

ObjectCaptureReconstruction/AppDataModel.swift:24 — representative stored state or nearest verified lifecycle anchor.

    private(set) var session: PhotogrammetrySession?

    // App's current state.
    var state: State = .ready {
        // ...
    }
Owner Object or state Relationship Mutation authority
AppDataModel PhotogrammetrySession as session stores and coordinates The declaring type controls writes
ContentView AppDataModel as appDataModel creates and retains The declaring type controls writes
AppDataModel PhotogrammetrySession as detailLevelOptionUnderQualityMenu stores and coordinates The owning type coordinates writes
AppDataModel Configuration as sessionConfiguration stores and coordinates The owning type coordinates writes

Ownership is intentionally narrow: environment, bindings, observed objects, weak links, and delegate callbacks do not prove lifetime ownership. Initialized stored services and wrapper-managed state do; entities added inside a RealityKit content closure belong to that entity graph.

Class and protocol design

Type Responsibility Depends on or conforms to
ObjectCaptureReconstructionApp (ObjectCaptureReconstruction/ObjectCaptureReconstructionApp.swift:11) Declares app lifecycle and top-level dependency lifetime. App
ContentView (ObjectCaptureReconstruction/ContentView.swift:10) Presents UI and forwards gestures or lifecycle events. View
AppDataModel (ObjectCaptureReconstruction/AppDataModel.swift:15) Owns feature state and domain transitions. Concrete framework collaborators
BottomBarView (ObjectCaptureReconstruction/Processing/BottomBarView.swift:15) Presents UI and forwards gestures or lifecycle events. View
FolderOptionsView (ObjectCaptureReconstruction/Settings/FolderOptions/FolderOptionsView.swift:11) Presents UI and forwards gestures or lifecycle events. View
IgnoreBoundingBoxView (ObjectCaptureReconstruction/Settings/ReconstructionOptions/IgnoreBoundingBoxView.swift:11) Presents UI and forwards gestures or lifecycle events. View
ImageFolderSelectionView (ObjectCaptureReconstruction/Settings/FolderOptions/ImageFolderSelectionView.swift:14) Presents UI and forwards gestures or lifecycle events. View
ImageFolderThumbnailView (ObjectCaptureReconstruction/Settings/FolderOptions/ImageFolderThumbnailView.swift:10) Presents UI and forwards gestures or lifecycle events. View

The reviewed source defines no local substitution protocol. Its App, View, delegate, renderer, ARKit, and RealityKit conformances are framework-facing contracts, so this document does not label the whole app protocol-oriented.

Access control

Symbol Access Verified effect Likely rationale
private(set) var session: PhotogrammetrySession? (ObjectCaptureReconstruction/AppDataModel.swift:24) private(set) The getter keeps its wider visibility, while writes stay in the declaring type and permitted same-file extensions. Inference: Protect an invariant while allowing observation.
private let logger = Logger(subsystem: ObjectCaptureReconstructionApp.s... (ObjectCaptureReconstruction/AppDataModel.swift:12) private Use stays inside the declaration and same-file extensions permitted by Swift. Inference: Hide lifecycle-sensitive state or an implementation step.
public var description: String { (ObjectCaptureReconstruction/AppDataModel.swift:149) public The symbol is available to importing modules, subject to its containing type’s visibility. Inference: Expose an intentional package or cross-target surface.

No reviewed Swift access example uses fileprivate, open; declarations without a modifier are internal.

Reference code

ObjectCaptureReconstruction/AppDataModel.swift:24 — representative visibility boundary.

    private(set) var session: PhotogrammetrySession?

    // App's current state.
    var state: State = .ready {
        // ...
    }

Logic ownership and placement

Logic Owning type or file Placement rationale
Application/command lifecycle ObjectCaptureReconstructionApp The executable boundary determines app, controller, scene, or command lifetime.
Presentation and user intent ContentView The view/controller forwards input and owns only presentation-local work.
Shared feature state and commands AppDataModel A stable owner prevents view recomputation or callbacks from duplicating transitions.
Capture/reconstruction session lifecycle ObjectCaptureReconstruction/AppDataModel.swift:24 Session creation and output handling stay outside render-only view code.

Design patterns

Pattern Source evidence Purpose or tradeoff
SwiftUI scene composition ObjectCaptureReconstruction/ObjectCaptureReconstructionApp.swift:11 Keeps windows, volumes, and immersive presentation visible at the app boundary.
UI–RealityKit bridge ObjectCaptureReconstruction/Processing/ModelView.swift:22 Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle.
Observable state owner ObjectCaptureReconstruction/AppDataModel.swift:15 Keeps shared feature state in a stable owner rather than in transient view values.
Session owner boundary ObjectCaptureReconstruction/AppDataModel.swift:24 Keeps authorization, session lifetime, and framework callbacks in a stable model, manager, or controller.
Async update consumer ObjectCaptureReconstruction/Processing/ReconstructionProgressView.swift:93 Consumes long-lived framework output in a cancellable asynchronous task.
Photogrammetry request pipeline ObjectCaptureReconstruction/AppDataModel.swift:24 Separates request creation, asynchronous output handling, and UI-facing reconstruction progress.

Naming conventions

  • Role suffixes are evidence, not decoration: App: ObjectCaptureReconstructionApp; Model: AppDataModel; View: BottomBarView, ContentView, FolderOptionsView, IgnoreBoundingBoxView, ImageFolderSelectionView.
  • Protocols: no app-defined protocol in the reviewed source.
  • Commands use verb-led methods: startReconstruction, createSession, createReconstructionRequests, hash, getImageName, getFirstImage, isLoadableImageFile.
  • Files and folders use primary-type or responsibility names such as Views, Models, Rendering, Components, Systems, Packages, or feature names where those boundaries exist.

Architecture takeaways

  • Treat ObjectCaptureReconstructionApp as the owner of executable or scene lifecycle, not automatically as the owner of every entity created later.
  • Keep view/controller input near presentation, but move sessions, reconstruction, capture, rendering, shared game state, or documents into stable owners when their lifetime exceeds one callback or render pass.
  • Tie asynchronous session/output consumers to an explicit owner so cancellation and teardown follow the same lifecycle.

Source map

Source file Relevant symbols
ObjectCaptureReconstruction/AppDataModel.swift:15 AppDataModel, State, DetailLevelOptionsUnderAdvancedMenu
ObjectCaptureReconstruction/ObjectCaptureReconstructionApp.swift:11 ObjectCaptureReconstructionApp
ObjectCaptureReconstruction/Settings/ReconstructionOptions/MaskingView.swift:11 MaskingView, MaskingOption
ObjectCaptureReconstruction/ContentView.swift:10 ContentView
ObjectCaptureReconstruction/Processing/BottomBarView.swift:15 BottomBarView
ObjectCaptureReconstruction/Settings/FolderOptions/FolderOptionsView.swift:11 FolderOptionsView
ObjectCaptureReconstruction/Settings/ReconstructionOptions/IgnoreBoundingBoxView.swift:11 IgnoreBoundingBoxView