Sample CodevisionOSReviewed 2026-07-21View on Apple Developer

Tracking a handheld accessory as a virtual sculpting tool

At a glance

Item Summary
Purpose Use a tracked accessory with Apple Vision Pro to create a virtual sculpture.
App architecture SpatialSculptingApp owns the document scene; SculptingToolModel maps ARKit accessory updates into tool pose and haptics, while compute and sculpting systems modify the volume document’s low-level resources.
Main patterns SwiftUI scene composition, UI–RealityKit bridge, Observable state owner, Entity-component-system, Protocol capability boundary, Tracked-input compute pipeline
Project style Code-rich sample with 25 scanned C/Objective-C header, Metal, Swift file(s) and 2033 implementation line(s).

Project structure

Source bundle/
└── SpatialSculpting/
    └── SpatialSculpting/
        ├── ViewModel/
        │   ├── SculptingToolModel.swift  # SculptingToolModel
        │   └── HapticsModel.swift  # HapticsModel
        ├── Document/
        │   └── VolumeDocument.swift  # VolumeDocumentError, VolumeDocument
        ├── SpatialSculptingApp.swift  # SpatialSculptingApp
        ├── Compute/
        │   └── ComputeSystem.swift  # ComputeUpdateContext, ComputeSystem, ComputeSystemComponent
        ├── ContentView.swift  # ContentView
        └── ECS/
            └── SculptingToolComponent.swift  # SculptingMode, SculptingToolComponent, SculptingToolSystem

Structure observations

  • The runtime boundary is WindowGroup + volumetric window + SwiftUI/UIKit host; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
  • The source is C/Objective-C header, Metal, Swift; role-named types and feature folders separate the major responsibilities.

Overall architecture

Reference code

SpatialSculpting/SpatialSculpting/SpatialSculptingApp.swift:11 — executable or app-lifecycle anchor.

struct SpatialSculptingApp: 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

SpatialSculpting/SpatialSculpting/ContentView.swift:23 — representative stored state or nearest verified lifecycle anchor.

struct ContentView: View {
    // ...
    @State var saveDocument: VolumeDocument? = nil
    // ...
}
Owner Object or state Relationship Mutation authority
ContentView VolumeDocument as saveDocument owns SwiftUI value state The owning type coordinates writes
SculptingToolModel Entity as rootEntity stores and coordinates The owning type coordinates writes
SculptingToolModel AnchorEntity as sculptingEntity stores and coordinates The owning type coordinates writes
SculptingToolModel ModelEntity as trackingStateIndicator 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
SpatialSculptingApp (SpatialSculpting/SpatialSculpting/SpatialSculptingApp.swift:11) Declares app lifecycle and top-level dependency lifetime. App
ContentView (SpatialSculpting/SpatialSculpting/ContentView.swift:14) Presents UI and forwards gestures or lifecycle events. View
SculptingToolModel (SpatialSculpting/SpatialSculpting/ViewModel/SculptingToolModel.swift:13) Owns feature state and domain transitions. Concrete framework collaborators
SculptingToolSystem (SpatialSculpting/SpatialSculpting/ECS/SculptingToolComponent.swift:38) Updates entities matching a RealityKit component query. ComputeSystem
ComputeSystem (SpatialSculpting/SpatialSculpting/Compute/ComputeSystem.swift:55) Declares a replaceable capability or collaboration contract. Concrete framework collaborators
ComputeSystemComponent (SpatialSculpting/SpatialSculpting/Compute/ComputeSystem.swift:61) Stores RealityKit entity data. Component
ComputeDispatchSystem (SpatialSculpting/SpatialSculpting/Compute/ComputeSystem.swift:66) Updates entities matching a RealityKit component query. System
SculptingToolComponent (SpatialSculpting/SpatialSculpting/ECS/SculptingToolComponent.swift:22) Stores RealityKit entity data. Component

Verified protocol-oriented seams: SculptingToolSystemComputeSystem. Framework conformances remain adapters, not proof of an app-wide protocol architecture.

Access control

Symbol Access Verified effect Likely rationale
private let marchPipeline: MTLComputePipelineState = makeComputePipelin... (SpatialSculpting/SpatialSculpting/Mesh/MarchingCubesMesh.swift:27) 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 triangleTable: [UInt64] = [ (SpatialSculpting/SpatialSculpting/Mesh/TriangleTable.swift:11) 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.

Objective-C/C header and implementation visibility is documented separately from Swift lexical access control.

Reference code

SpatialSculpting/SpatialSculpting/Mesh/MarchingCubesMesh.swift:27 — representative visibility boundary.

    private let marchPipeline: MTLComputePipelineState = makeComputePipeline(named: "march")!
    // Compute pipeline corresponding to the Metal compute shader function `clear`.
    //
    // See `MarchingCubesCompute.metal`.
    private let clearPipeline: MTLComputePipelineState = makeComputePipeline(named: "clear")!

Logic ownership and placement

Logic Owning type or file Placement rationale
Application/command lifecycle SpatialSculptingApp 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 SculptingToolModel A stable owner prevents view recomputation or callbacks from duplicating transitions.
Framework/session/render coordination SculptingToolSystem The role-named collaborator isolates long-lived or per-frame work from presentation code.
Per-entity data and repeated behavior SpatialSculpting/SpatialSculpting/Compute/ComputeSystem.swift:66 Components carry data; the system queries and updates matching entities.
GPU and low-level resource work SpatialSculpting/SpatialSculpting/Mesh/MarchingCubesMesh.swift:11 Buffer, texture, shader, or frame-resource mutation stays in a rendering/compute boundary.

Design patterns

Pattern Source evidence Purpose or tradeoff
SwiftUI scene composition SpatialSculpting/SpatialSculpting/SpatialSculptingApp.swift:11 Keeps windows, volumes, and immersive presentation visible at the app boundary.
UI–RealityKit bridge SpatialSculpting/SpatialSculpting/ContentView.swift:51 Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle.
Observable state owner SpatialSculpting/SpatialSculpting/ViewModel/SculptingToolModel.swift:13 Keeps shared feature state in a stable owner rather than in transient view values.
Entity-component-system SpatialSculpting/SpatialSculpting/Compute/ComputeSystem.swift:66 Stores per-entity data in components and advances repeated behavior in registered systems.
Protocol capability boundary SpatialSculpting/SpatialSculpting/ECS/SculptingToolComponent.swift:38 Defines a local capability with concrete conformers; this is the verified protocol-oriented seam.
Tracked-input compute pipeline SpatialSculpting/SpatialSculpting/ViewModel/SculptingToolModel.swift:13 Maps accessory tracking and haptics into tool state before compute systems modify the sculpted volume.

Naming conventions

  • Role suffixes are evidence, not decoration: App: SpatialSculptingApp; Model: HapticsModel, SculptingToolModel; Document: VolumeDocument; System: ComputeDispatchSystem, ComputeSystem, SculptingToolSystem; Component: ComputeSystemComponent, SculptingToolComponent.
  • ECS names pair data and behavior: components ComputeSystemComponent, SculptingToolComponent; systems ComputeDispatchSystem, SculptingToolSystem.
  • Protocols: ComputeSystem.
  • Commands use verb-led methods: selectToolbarElement, displayToolbar, handlePalettePress, updateTrackingStateIndicatorIfDirty, updateSculptingTool, addEntityAttachmentToRoot, loadFromURL, fileWrapper.
  • 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 SpatialSculptingApp 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.
  • Use components for per-entity data and systems for repeated simulation instead of centralizing every update in a view model or controller.

Source map

Source file Relevant symbols
SpatialSculpting/SpatialSculpting/ViewModel/SculptingToolModel.swift:13 SculptingToolModel
SpatialSculpting/SpatialSculpting/Document/VolumeDocument.swift:11 VolumeDocumentError, VolumeDocument
SpatialSculpting/SpatialSculpting/SpatialSculptingApp.swift:11 SpatialSculptingApp
SpatialSculpting/SpatialSculpting/Compute/ComputeSystem.swift:12 ComputeUpdateContext, ComputeSystem, ComputeSystemComponent, ComputeDispatchSystem
SpatialSculpting/SpatialSculpting/ContentView.swift:14 ContentView
SpatialSculpting/SpatialSculpting/ECS/SculptingToolComponent.swift:12 SculptingMode, SculptingToolComponent, SculptingToolSystem
SpatialSculpting/SpatialSculpting/ViewModel/HapticsModel.swift:15 HapticsModel