Sample CodemacOSReviewed 2026-07-21View on Apple Developer

Creating a photogrammetry command-line app

At a glance

Item Summary
Purpose Generate 3D objects from images using RealityKit Object Capture.
App architecture Top-level main.swift defines HelloPhotogrammetry, parses command options, creates a PhotogrammetrySession, submits one request, and consumes the session’s asynchronous output stream.
Main patterns Session owner boundary, Async update consumer, Async session-output consumer
Project style Code-light sample with 1 scanned Swift file(s) and 237 implementation line(s).

Project structure

Source bundle/
└── HelloPhotogrammetry/
    └── main.swift  # HelloPhotogrammetry, IllegalOption

Structure observations

  • The runtime boundary is top-level command; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
  • The source is Swift; its compact size does not erase any explicit owner shown below.

Overall architecture

Reference code

HelloPhotogrammetry/main.swift:19 — executable or app-lifecycle anchor.

struct HelloPhotogrammetry: ParsableCommand {
    // ...
}

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

HelloPhotogrammetry/main.swift:24 — representative stored state or nearest verified lifecycle anchor.

    public static let configuration = CommandConfiguration(
        abstract: "Reconstructs 3D USDZ model from a folder of images.")
    
    @Argument(help: "The local input file folder of images.")
    private var inputFolder: String
    
    @Argument(help: "Full path to the USDZ output file.")
    private var outputFilename: String
Owner Object or state Relationship Mutation authority
HelloPhotogrammetry CommandConfiguration as configuration creates and retains The owning type coordinates writes
HelloPhotogrammetry Detail as detail stores and coordinates The declaring type controls writes
HelloPhotogrammetry SampleOrdering as sampleOrdering stores and coordinates The declaring type controls writes
HelloPhotogrammetry FeatureSensitivity as featureSensitivity stores and coordinates The declaring type controls 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
HelloPhotogrammetry (HelloPhotogrammetry/main.swift:19) Represents a feature value or composable behavior. ParsableCommand

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 let logger = Logger(subsystem: "com.apple.sample.photogrammetry", (HelloPhotogrammetry/main.swift:14) private Use stays inside the declaration and same-file extensions permitted by Swift. Inference: Hide lifecycle-sensitive state or an implementation step.
public static let configuration = CommandConfiguration( (HelloPhotogrammetry/main.swift:24) 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, private(set), open; declarations without a modifier are internal.

Reference code

HelloPhotogrammetry/main.swift:14 — representative visibility boundary.

private let logger = Logger(subsystem: "com.apple.sample.photogrammetry",
                            category: "HelloPhotogrammetry")

Logic ownership and placement

Logic Owning type or file Placement rationale
Application/command lifecycle HelloPhotogrammetry The executable boundary determines app, controller, scene, or command lifetime.
Shared feature state and commands HelloPhotogrammetry A stable owner prevents view recomputation or callbacks from duplicating transitions.
Capture/reconstruction session lifecycle HelloPhotogrammetry/main.swift:21 Session creation and output handling stay outside render-only view code.

Design patterns

Pattern Source evidence Purpose or tradeoff
Session owner boundary HelloPhotogrammetry/main.swift:21 Keeps authorization, session lifetime, and framework callbacks in a stable model, manager, or controller.
Async update consumer HelloPhotogrammetry/main.swift:79 Consumes long-lived framework output in a cancellable asynchronous task.
Async session-output consumer HelloPhotogrammetry/main.swift:21 Streams progress, completion, and failures from a long-running photogrammetry session without a UI layer.

Naming conventions

  • Role suffixes are evidence, not decoration: feature nouns and framework type names dominate this compact sample.
  • Protocols: no app-defined protocol in the reviewed source.
  • Commands use verb-led methods: run, makeConfigurationFromArguments, makeRequestFromArguments, handleRequestComplete, handleRequestProgress.
  • 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 HelloPhotogrammetry 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.
  • The compact source does not justify repository, coordinator, or protocol layers beyond boundaries the sample actually declares.

Source map

Source file Relevant symbols
HelloPhotogrammetry/main.swift:19 HelloPhotogrammetry, IllegalOption