Sample CodevisionOSReviewed 2026-07-21View on Apple Developer

Transforming RealityKit entities using gestures

At a glance

Item Summary
Purpose Build a RealityKit component to support standard visionOS gestures on any entity.
App architecture EntityGestureApp loads content in ContentView; GestureComponent stores per-entity interaction configuration and gesture modifiers translate drag, rotate, and scale input into entity transforms.
Main patterns SwiftUI scene composition, UI–RealityKit bridge, Authored-content boundary, Entity gesture component
Project style Code-rich sample with 8 scanned Swift file(s) and 523 implementation line(s).

Project structure

Source bundle/
├── Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift  # EntityGestureState, GestureComponent
├── EntityGestures/ContentView.swift  # ContentView
├── EntityGestures/EntityGestureApp.swift  # EntityGestureApp
├── Packages/RealityKitContent/Sources/RealityKitContent/Extensions/EntityExtensions.swift
├── Packages/RealityKitContent/Sources/RealityKitContent/Extensions/GestureExtensions.swift
├── Packages/RealityKitContent/Sources/RealityKitContent/Extensions/RealityViewExtensions.swift
├── Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift
└── Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json  # authored RealityKit content

Structure observations

  • The runtime boundary is WindowGroup + volumetric 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.
  • Authored .reality, .rkassets, or Reality Composer Pro content is an implementation boundary; Swift loads or drives it rather than reproducing its entity graph.

Overall architecture

Reference code

EntityGestures/EntityGestureApp.swift:12 — executable or app-lifecycle anchor.

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

Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:120 — representative stored state or nearest verified lifecycle anchor.

@MainActor
public struct GestureComponent: Component, Codable {
    // ...
            let pivotEntity = Entity()
    // ...
}
Owner Object or state Relationship Mutation authority
GestureComponent Entity as pivotEntity creates and retains The owning type coordinates writes
EntityGestureState Entity as targetedEntity stores and coordinates The owning type coordinates writes
EntityGestureState Entity as pivotEntity stores and coordinates The owning type coordinates writes
GestureComponent Transform as targetPivotTransform creates and retains 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
EntityGestureApp (EntityGestures/EntityGestureApp.swift:12) Declares app lifecycle and top-level dependency lifetime. App
ContentView (EntityGestures/ContentView.swift:12) Presents UI and forwards gestures or lifecycle events. View
GestureComponent (Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:55) Stores RealityKit entity data. Component, Codable

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
public var canDrag: Bool = true (Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:58) 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

Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:58 — representative visibility boundary.

@MainActor
public struct GestureComponent: Component, Codable {
    // ...
    public var canDrag: Bool = true
    // ...
}

Logic ownership and placement

Logic Owning type or file Placement rationale
Application/command lifecycle EntityGestureApp 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.
Framework/session/render coordination GestureComponent The role-named collaborator isolates long-lived or per-frame work from presentation code.
Authored scene composition Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json Reality Composer Pro owns hierarchy, materials, animation, or behavior that Swift loads and coordinates.

Design patterns

Pattern Source evidence Purpose or tradeoff
SwiftUI scene composition EntityGestures/EntityGestureApp.swift:12 Keeps windows, volumes, and immersive presentation visible at the app boundary.
UI–RealityKit bridge EntityGestures/ContentView.swift:50 Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle.
Authored-content boundary EntityGestures/ContentView.swift:10 Treats Reality Composer Pro assets as implementation and keeps Swift responsible for loading and runtime coordination.
Entity gesture component Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:11 Stores interaction policy with the entity and keeps drag, rotation, and scale translation in reusable gesture modifiers.

Naming conventions

  • Role suffixes are evidence, not decoration: App: EntityGestureApp; Component: GestureComponent; View: ContentView.
  • ECS names pair data and behavior: components GestureComponent; systems none.
  • Protocols: no app-defined protocol in the reviewed source.
  • Commands use verb-led methods: onChanged, handlePivotDrag, handleFixedDrag, onEnded, useGestureComponent, installGestures.
  • 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 EntityGestureApp 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.
  • Count authored Reality Composer Pro assets as implementation; the Swift shell is not the complete architecture.

Source map

Source file Relevant symbols
Packages/RealityKitContent/Sources/RealityKitContent/Components/GestureComponent.swift:11 EntityGestureState, GestureComponent
EntityGestures/ContentView.swift:12 ContentView
EntityGestures/EntityGestureApp.swift:12 EntityGestureApp
Packages/RealityKitContent/Sources/RealityKitContent/Extensions/EntityExtensions.swift:1 Feature implementation
Packages/RealityKitContent/Sources/RealityKitContent/Extensions/GestureExtensions.swift:1 Feature implementation
Packages/RealityKitContent/Sources/RealityKitContent/Extensions/RealityViewExtensions.swift:1 Feature implementation
Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift:1 Feature implementation