Destination Video
At a glance
| Item | Summary |
|---|---|
| Purpose | Leverage SwiftUI to build an immersive media experience in a multiplatform app. |
| App architecture | DestinationVideo creates the SwiftData catalog and PlayerModel; player and watching coordinators split AVPlayer lifetime, presentation state, and SharePlay synchronization. |
| Main patterns | SwiftUI scene composition, SwiftUI–RealityKit bridge, Explicit immersive-space lifecycle, Observable state owner, Async update consumer, Playback coordinator adapter |
| Project style | Code-rich sample with 46 scanned Swift file(s) and 4372 Swift line(s); resources and generated assets are excluded from those counts. |
Project structure
Source bundle/
├── DestinationVideo/DestinationVideo.swift # DestinationVideo
├── DestinationVideo/Player/PlayerModel.swift # Presentation, PlayerModel, PlayerViewObserver
├── DestinationVideo/SharePlay/WatchingCoordinator.swift # WatchingCoordinator, PlaybackCoordinatorDelegate
├── DestinationVideo/Views/VideoInfoView.swift # InfoView, GenreView, RoleView
├── DestinationVideo/ContentView.swift # ContentView
├── DestinationVideo/Player/SystemPlayerView.swift # SystemPlayerView, Coordinator, SystemPlayerView
├── DestinationVideo/Views/CategoryListView.swift # CategoryListView
├── DestinationVideo/Views/visionOS/ImmersiveEnvironmentView.swift # ImmersiveEnvironmentView
└── Packages/Studio/Package.realitycomposerpro/ProjectData/main.json # authored RealityKit content
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.
- Authored
.realityor Reality Composer Pro content is a real implementation boundary; Swift loads or drives it rather than reproducing its entity graph. - Covers the complete multi-platform sample: SwiftData catalog, player ownership, SharePlay coordination, and visionOS presentation.
Overall architecture
flowchart LR
DestinationVideo_1["DestinationVideo"]
WindowGroup___ImmersiveSpace_2["WindowGroup + ImmersiveSpace"]
ContentView_3["ContentView"]
PlayerModel_4["PlayerModel"]
RealityView_entity_graph_5["RealityView entity graph"]
AV_playback___system_presentation_6["AV playback + system presentation"]
DestinationVideo_1 --> WindowGroup___ImmersiveSpace_2
WindowGroup___ImmersiveSpace_2 --> ContentView_3
ContentView_3 --> PlayerModel_4
PlayerModel_4 --> RealityView_entity_graph_5
RealityView_entity_graph_5 --> AV_playback___system_presentation_6
Reference code
DestinationVideo/DestinationVideo.swift:14 — the app or executable entry declares the outer scene lifecycle.
struct DestinationVideo: 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
classDiagram
DestinationVideo *-- PlayerModel : player
DestinationVideo --> ModelContainer : modelContainer
ContentView o-- PlayerModel : player
DestinationVideo *-- ImmersiveEnvironment : immersiveEnvironment
Ownership evidence
DestinationVideo/DestinationVideo.swift:19 — representative stored state or the nearest verified lifecycle anchor.
@main
struct DestinationVideo: App {
// ...
@State private var player: PlayerModel
// ...
}| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
DestinationVideo |
PlayerModel as player |
owns a SwiftUI-managed reference slot | Only the declaring scope writes |
DestinationVideo |
ModelContainer as modelContainer |
stores and coordinates | Only the declaring scope writes |
ContentView |
PlayerModel as player |
receives a shared/non-owning reference | The upstream owner controls lifetime; this scope may invoke its mutable API |
DestinationVideo |
ImmersiveEnvironment as immersiveEnvironment |
creates and retains | Only the declaring scope writes |
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 |
|---|---|---|
DestinationVideo (DestinationVideo/DestinationVideo.swift:14) |
Declares app scenes and top-level dependency lifetime. | App |
ContentView (DestinationVideo/ContentView.swift:11) |
Presents UI and forwards gestures or lifecycle events. | View |
PlayerModel (DestinationVideo/Player/PlayerModel.swift:21) |
Owns observable feature state and domain transitions. | Concrete framework collaborators |
Coordinator (DestinationVideo/Player/SystemPlayerView.swift:25) |
Coordinates long-lived framework or cross-view work. | NSObject, AVPlayerViewDelegate |
WatchingCoordinator (DestinationVideo/SharePlay/WatchingCoordinator.swift:14) |
Coordinates long-lived framework or cross-view work. | Concrete framework collaborators |
PlaybackCoordinatorDelegate (DestinationVideo/SharePlay/WatchingCoordinator.swift:155) |
Provides a sample-specific value or framework adapter. | NSObject, AVPlayerPlaybackCoordinatorDelegate |
CategoryListView (DestinationVideo/Views/CategoryListView.swift:11) |
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 |
|---|---|---|---|
public private(set) var activeState: EnvironmentStateType = .none (DestinationVideo/Model/visionOS/EnvironmentStateHandler.swift:45) |
private(set) |
The getter keeps its wider visibility, while mutation stays inside the declaring type and its permitted same-file extensions. | Inference: Protect a state invariant while allowing observation. |
@Environment(PlayerModel.self) private var player (DestinationVideo/ContentView.swift:12) |
private |
Use is restricted to the declaration and same-file extensions permitted by Swift. | Inference: Hide implementation details and lifecycle-sensitive state. |
public var lightStateVisualEntity: Entity? { (DestinationVideo/Model/visionOS/EnvironmentStateHandler.swift:110) |
public |
The declaration is available to importing modules, subject to its containing type’s visibility. | Inference: Satisfy a cross-target or framework-facing surface without implying subclassability. |
No reviewed declaration uses fileprivate, open; unmodified Swift declarations are internal.
Reference code
DestinationVideo/Model/visionOS/EnvironmentStateHandler.swift:45 — representative visibility boundary.
public private(set) var activeState: EnvironmentStateType = .none
public func gatherEntities(from rootEntity: Entity?) {
// ...
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Scene declaration and dependency lifetime | DestinationVideo |
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 | PlayerModel |
A role-named owner prevents sibling views from duplicating transitions. |
| Playback resource lifecycle | DestinationVideo/Player/PlayerModel.swift:39 |
The player/component owner survives view recomputation and drives system presentation. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| SwiftUI scene composition | DestinationVideo/DestinationVideo.swift:14 |
Keeps windows, volumes, and immersive-space lifecycle visible at the app boundary. |
| SwiftUI–RealityKit bridge | DestinationVideo/Views/visionOS/ImmersiveEnvironmentView.swift:20 |
Builds and updates a RealityKit entity graph from SwiftUI lifecycle closures. |
| Explicit immersive-space lifecycle | DestinationVideo/DestinationVideo.swift:63 |
Makes immersive presentation a scene transition rather than hidden global state. |
| Observable state owner | DestinationVideo/Player/PlayerModel.swift:21 |
Shares feature state across multiple views without moving framework resources into view values. |
| Async update consumer | DestinationVideo/Player/PlayerModel.swift:157 |
Consumes provider or event streams in cancellable structured tasks. |
| Playback coordinator adapter | DestinationVideo/Player/PlayerModel.swift:57 |
Keeps local playback and SharePlay coordination behind one player-facing boundary. |
Naming conventions
- Role suffixes are evidence, not decoration: Model:
PlayerModel; Coordinator:Coordinator,WatchingCoordinator; Delegate:PlaybackCoordinatorDelegate; View:CategoryListView,CategoryView,ContentView,DetailView,GenreView. - Protocols: no app-defined protocol in the reviewed source.
- Commands use verb-led methods:
makePlayerUI,willEndFullScreenPresentation,playerViewController,observePlayback,configureAudioSession,observeSharedVideo,loadVideo,replaceCurrentItem. - Files generally match their primary type;
Views,Models,Managers,Providers,Components,Systems, andPackagesfolders describe architectural roles where present.
Architecture takeaways
- Treat
DestinationVideoas 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.
- Model immersive-space open, transition, and close states explicitly so windows and immersive content cannot drift apart.
Source map
| Source file | Relevant symbols |
|---|---|
DestinationVideo/DestinationVideo.swift:14 |
DestinationVideo |
DestinationVideo/Player/PlayerModel.swift:13 |
Presentation, PlayerModel, PlayerViewObserver |
DestinationVideo/SharePlay/WatchingCoordinator.swift:14 |
WatchingCoordinator, PlaybackCoordinatorDelegate |
DestinationVideo/Views/VideoInfoView.swift:11 |
InfoView, GenreView, RoleView, PosterCard |
DestinationVideo/ContentView.swift:11 |
ContentView |
DestinationVideo/Player/SystemPlayerView.swift:14 |
SystemPlayerView, Coordinator, SystemPlayerView |
DestinationVideo/Views/CategoryListView.swift:11 |
CategoryListView |
DestinationVideo/Views/visionOS/ImmersiveEnvironmentView.swift:13 |
ImmersiveEnvironmentView |