Sample CodeiOS 18.1+, iPadOS 18.1+, Mac Catalyst 18.1+, macOS 15.1+, visionOS 2.1+, watchOS 11.0+Reviewed 2026-07-21View on Apple Developer

Accelerating app interactions with App Intents

At a glance

Item Summary
Purpose Demonstrate App Intents, entities, queries, shortcuts, Spotlight, foreground navigation, and workout controls.
Architecture A SwiftUI trail app exposes thin intent/entity adapters over observable managers and value models.
Targets The Xcode project contains host-app and watch-app targets; shared source uses platform conditionals for watchOS workout behavior.
Main pattern The app registers long-lived managers once; @Dependency gives intents and entity queries the same behavior owners.

Project structure

AppIntentsSampleApp/
├── AppIntentsSampleApp.swift
├── App Intents/
│   ├── Entities/
│   └── Workout Intents/
├── Model/                  # trail, account, navigation, activity managers
├── Views/
└── Utililty/

The app and watch targets share source membership; there is no separate extension target or library package.

Overall architecture

Reference code

AppIntentsSampleApp/AppIntentsSampleApp.swift:19 — composition happens at the earliest non-UI-dependent launch path (abridged).

let trailDataManager = TrailDataManager.shared
let navigationModel = NavigationModel(
    selectedCollection: trailDataManager.nearMeCollection
)
let activityTracker = ActivityTracker.shared

AppDependencyManager.shared.add(dependency: trailDataManager)
AppDependencyManager.shared.add(dependency: navigationModel)
AppDependencyManager.shared.add(dependency: activityTracker)

Ownership and state

Ownership evidence

AppIntentsSampleApp/Model/ActivityTracker.swift:14 — one manager owns activity history and conditionally owns the watch implementation.

@Observable class ActivityTracker: ActivityTrackingActions, @unchecked Sendable {
    static let shared = ActivityTracker()
    private(set) var activityHistory: [Activity]
    private(set) var activityInProgress: Activity?
    private var liveWorkoutManager: ActivityTrackingActions?
}

Managers are the mutation authorities. Views receive them through SwiftUI environment; App Intents receive the same instances through App Intents dependency injection.

Class and protocol design

TrailEntity: AppEntity is deliberately separate from Trail, exposing only system-relevant data (AppIntentsSampleApp/App Intents/Entities/TrailEntity.swift:11). Intent structs adopt specialized framework protocols such as OpenIntent and StartWorkoutIntent. The private ActivityTrackingActions protocol at AppIntentsSampleApp/Model/ActivityTracker.swift:257 lets the cross-platform tracker substitute a watchOS HealthKit implementation without exposing that abstraction app-wide.

Access control

Symbol Access Rationale
Root manager properties private Only app composition injects them (AppIntentsSampleApp/AppIntentsSampleApp.swift:14).
Intent dependencies private where callers need no access Keeps framework-populated collaborators implementation-only (AppIntentsSampleApp/App Intents/OpenFavorites.swift:46).
Activity history setters private(set) Views/intents may read; only tracker transitions state.
LiveWorkoutManager and strategy protocol private They are watchOS implementation details in one file.
Public API none Both targets compile app-owned source, not a distributable library.

Logic ownership and placement

Logic Owner Placement reason
Trail loading/querying and Spotlight TrailDataManager + extension All entity/query paths use one catalog (AppIntentsSampleApp/Model/TrailDataManager.swift:90).
Foreground selection NavigationModel UI state remains main-actor isolated.
Workout lifecycle/history ActivityTracker Keeps platform-neutral history and watch-specific delegation together.
Entity translation TrailEntity initializer/query System representation remains outside the domain value.
Intent orchestration Individual intent perform() Thin adapters resolve input and call owners (AppIntentsSampleApp/App Intents/OpenFavorites.swift:33).

Design patterns

Pattern Evidence Purpose
Composition root / DI App registers four managers Supports background intent execution without requiring a scene.
Entity adapter TrailEntity omits heavy images Keeps system-facing values stable and minimal.
Repository TrailDataManager query API One trail source for UI, Spotlight, and intents.
Router NavigationModel Intent-driven foreground navigation changes observable state.
Strategy protocol ActivityTrackingActions Adds HealthKit only on watchOS.

Naming conventions

  • System entry points use verb-first names (OpenFavorites, SuggestTrails, StartTrailActivity).
  • Framework roles use suffixes (Entity, EntityQuery, OptionsProvider, Manager, Tracker).
  • Domain values remain singular (Trail, Activity); owning collections/managers use broader nouns.

Architecture takeaways

  • Register intent dependencies before any code assumes a visible scene.
  • Keep entity schemas separate when the app model contains expensive or irrelevant fields.
  • Use one mutation owner for UI and system entry points.
  • Treat the watch target as a platform specialization of shared architecture, not an extension process.

Source map

Source Role
AppIntentsSampleApp/AppIntentsSampleApp.swift:51 SwiftUI environment composition
AppIntentsSampleApp/Model/NavigationModel.swift:13 Main-actor UI state
AppIntentsSampleApp/Model/TrailDataManager.swift:12 Trail repository
AppIntentsSampleApp/App Intents/Entities/TrailEntity.swift:19 System entity adapter
AppIntentsSampleApp/App Intents/Workout Intents/StartTrailActivity.swift:16 Watch workout intent