Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2025 AI & Machine Learning

WWDC25 · 25 min · AI & Machine Learning

Get to know App Intents

Learn about the App Intents framework and its increasingly critical role within Apple’s developer platforms. We’ll take you through a ground-up introduction of the core concepts: intents, entities, queries, and much more. You’ll learn how these pieces fit together and let you integrate your app through Apple’s devices, from software features like Spotlight and Shortcuts to hardware features like the Action button. We’ll also walk through how App Intents is your app’s gateway to integrating with Apple Intelligence going forward.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 21 snippets

Navigate Intent swift · at 3:23 ↗
struct NavigateIntent: AppIntent {
    static let title: LocalizedStringResource = "Navigate to Landmarks"

    static let supportedModes: IntentModes = .foreground

    @MainActor
    func perform() async throws -> some IntentResult {
        Navigator.shared.navigate(to: .landmarks)
        return .result()
    }
}
Navigation Option App Enum swift · at 5:02 ↗
enum NavigationOption: String, AppEnum {
    case landmarks
    case map
    case collections

    static let typeDisplayRepresentation: TypeDisplayRepresentation = "Navigation Option"

    static let caseDisplayRepresentations: [NavigationOption: DisplayRepresentation] = [
        .landmarks: "Landmarks",
        .map: "Map",
        .collections: "Collections"
    ]
}
Navigate Intent with Parameter swift · at 5:38 ↗
struct NavigateIntent: AppIntent {
    static let title: LocalizedStringResource = "Navigate to Section"

    static let supportedModes: IntentModes = .foreground
  
    @Parameter var navigationOption: NavigationOption

    @MainActor
    func perform() async throws -> some IntentResult {
        Navigator.shared.navigate(to: navigationOption)
        return .result()
    }
}
Case Display Representations with Images swift · at 6:57 ↗
static let caseDisplayRepresentations = [
    NavigationOption.landmarks: DisplayRepresentation(
        title: "Landmarks",
        image: .init(systemName: "building.columns")
    ),
    NavigationOption.map: DisplayRepresentation(
        title: "Map",
        image: .init(systemName: "map")
    ),
    NavigationOption.collections: DisplayRepresentation(
        title: "Collections",
        image: .init(systemName: "book.closed")
    )
]
Navigation Option With Parameter Summary swift · at 7:28 ↗
struct NavigateIntent: AppIntent {
    static let title: LocalizedStringResource = "Navigate to Section"

    static let supportedModes: IntentModes = .foreground
  
    static var parameterSummary: some ParameterSummary {
        Summary("Navigate to \(\.$navigationOption)")
    }
  
    @Parameter(
        title: "Section",
        requestValueDialog: "Which section?"
    )
    var navigationOption: NavigationOption

    @MainActor
    func perform() async throws -> some IntentResult {
        Navigator.shared.navigate(to: navigationOption)
        return .result()
    }
}
App Shortcuts Provider and Navigation Intent App Shortcut swift · at 9:22 ↗
struct TravelTrackingAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: NavigateIntent(),
            phrases: [
                "Navigate in \(.applicationName)",
                "Navigate to \(\.$navigationOption) in \(.applicationName)"a
            ],                
            shortTitle: "Navigate",
            systemImageName: "arrowshape.forward"
        )
    }
}
Landmark Entity swift · at 11:02 ↗
struct LandmarkEntity: AppEntity {
    var id: Int { landmark.id }

    @ComputedProperty
    var name: String { landmark.name }

    @ComputedProperty
    var description: String { landmark.description }
  
    let landmark: Landmark
  
    static let typeDisplayRepresentation = TypeDisplayRepresentation(name: "Landmark")

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(name)")
    }
  
    static let defaultQuery = LandmarkEntityQuery()
}
Landmark Entity Query swift · at 13:19 ↗
struct LandmarkEntityQuery: EntityQuery {
    @Dependency var modelData: ModelData
  
    func entities(for identifiers: [LandmarkEntity.ID]) async throws -> [LandmarkEntity] {
        modelData
            .landmarks(for: identifiers)
            .map(LandmarkEntity.init)
    }
}
App Dependency Manager swift · at 13:50 ↗
@main
struct LandmarksApp: App {    
    init() {
        AppDependencyManager.shared.add { ModelData() }
    }
}
Closest Landmark Intent swift · at 14:18 ↗
struct ClosestLandmarkIntent: AppIntent {
    static let title: LocalizedStringResource = "Find Closest Landmark"

    @Dependency var modelData: ModelData

    @MainActor
    func perform() async throws 
        -> some ReturnsValue<LandmarkEntity> & ProvidesDialog & ShowsSnippetView {
        
        let landmark = try await modelData.findClosestLandmark()

        return .result(
            value: landmark,
            dialog: "The closest landmark to you is \(landmark.name)",
            view: ClosestLandmarkView(landmark: landmark)
        )
    }
}
Closest Landmark App Shortcut swift · at 15:18 ↗
AppShortcut(
    intent: ClosestLandmarkIntent(),
    phrases: [
        "Find closest landmark in \(.applicationName)"
    ],
    shortTitle: "Closest landmark",
    systemImageName: "location"
)
Transferable swift · at 16:33 ↗
extension LandmarkEntity: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .image) {
            return try $0.imageRepresentationData
        }
    }
}
Indexed Entity swift · at 17:31 ↗
struct LandmarkEntity: IndexedEntity {
    // ...
    
    @Property(
        indexingKey: \.displayName
    )
    var name: String

    @Property(
        indexingKey: \.contentDescription
    )
    var description: String
}
Open Landmark Intent swift · at 18:17 ↗
struct OpenLandmarkIntent: OpenIntent, TargetContentProvidingIntent {
    static let title: LocalizedStringResource = "Open Landmark"

    @Parameter(title: "Landmark", requestValueDialog: "Which landmark?")
    var target: LandmarkEntity
}

struct LandmarksNavigationStack: View {
    @State var path: [Landmark] = []

    var body: some View {
        NavigationStack(path: $path) {}
        .onAppIntentExecution(OpenLandmarkIntent.self) { intent in
            path.append(intent.target.landmark)
        }
    }
}
Open Landmark App Shortcut swift · at 19:24 ↗
AppShortcut(
    intent: OpenLandmarkIntent(),
    phrases: [
        "Open \(\.$target) in \(.applicationName)",
        "Open landmark in \(.applicationName)"
    ],
    shortTitle: "Open",
    systemImageName: "building.columns"
)
Suggested Entities swift · at 19:39 ↗
struct LandmarkEntityQuery: EntityQuery {
    // ...

    func suggestedEntities() async throws -> [LandmarkEntity] {
        modelData
            .favoriteLandmarks()
            .map(LandmarkEntity.init)
    }
}
Update App Shortcut Parameters swift · at 20:06 ↗
TravelTrackingAppShortcuts.updateAppShortcutParameters()
EnumerableEntityQuery swift · at 20:25 ↗
extension LandmarkEntityQuery: EnumerableEntityQuery {
    func allEntities() async throws -> [LandmarkEntity] { 
        // ...
    }
}
EntityPropertyQuery swift · at 20:36 ↗
extension LandmarkEntityQuery: EntityPropertyQuery {
    static var properties = QueryProperties {
        // ...
    }

    static var sortingOptions = SortingOptions {
        // ...
    }

    func entities(
        matching comparators: [Predicate<LandmarkEntity>],
        mode: ComparatorMode,
        sortedBy: [Sort<LandmarkEntity>],
        limit: Int?
    ) async throws -> [LandmarkEntity] {
        // ...
    }
}
EntityStringQuery swift · at 20:44 ↗
extension LandmarkEntityQuery: EntityStringQuery {
    func entities(matching: String) async throws -> [LandmarkEntity] {
        modelData
            .landmarks
            .filter { $0.name.contains(matching) || $0.description.contains(matching) }
            .map(LandmarkEntity.init)
    }
}
App Intents Package swift · at 23:10 ↗
// TravelTrackingKit
public struct TravelTrackingKitPackage: AppIntentsPackage {}
public structaLandmarkEntity: AppEntity {}

// TravelTracking
struct TravelTrackingPackage: AppIntentsPackage {
    static var includedPackages: [any AppIntentsPackage.Type] {
        [TravelTrackingKitPackage.self]
    }
}
struct OpenLandmarkIntent: OpenIntent {}

// TravelTrackingAppIntentsExtension
struct TravelTrackingExtensionPackage: AppIntentsPackage {
    static var includedPackages: [any AppIntentsPackage.Type] {
        [TravelTrackingKitPackage.self]
    }
}
struct FavoriteLandmarkIntent: AppIntent {}

Resources