2022 App Services
WWDC22 · 23 min · App Services
Implement App Shortcuts with App Intents
Discover how you can create Shortcuts in your app with zero user setup. We’ll show you how App Intents can help you present custom Shortcuts views, and explore how you can add support for parameterized phrases to allow people to quickly express their intent. We’ll also share how you can make your App Shortcuts discoverable with a Siri Tip, and Shortcuts links. To get the most out of this session, we recommend a basic familiarity with SwiftUI.
Watch at developer.apple.com ↗Code shown on screen · 11 snippets
Implement an AppIntent
// StartMeditationIntent creates a meditation session.
import AppIntents
struct StartMeditationIntent: AppIntent {
static let title: LocalizedStringResource = "Start Meditation Session"
func perform() async throws -> some IntentResult & ProvidesDialog {
await MeditationService.startDefaultSession()
return .result(dialog: "Okay, starting a meditation session.")
}
} Create an AppShortcutsProvider
// An AppShortcut turns an Intent into a full fledged shortcut
// AppShortcuts are returned from a struct that implements the AppShortcuts
// protocol
import AppIntents
struct MeditationShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: StartMeditationIntent(),
phrases: ["Start a \(.applicationName)"]
)
}
} Provide multiple phrases
// An AppShortcut turns an Intent into a full fledged shortcut
// AppShortcuts are returned from a struct that implements the AppShortcuts
// protocol
import AppIntents
struct MeditationShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: StartMeditationIntent(),
phrases: [
"Start a \(.applicationName)",
"Begin \(.applicationName)",
"Meditate with \(.applicationName)",
"Start a session with \(.applicationName)"
]
)
}
} Provide a dialog and snippet view
// Custom views give your intent more personality
// and can convey more information
func perform() async throws -> some ProvidesDialog & ShowsSnippetView {
await MeditationService.startDefaultSession()
return .result(
dialog: "Okay, starting a meditation session.",
view: MeditationSnippetView()
)
} Implement an AppEntity
// An entity is a type that can be used as a parameter
// for an AppIntent.
import AppIntents
struct MeditationSession: AppEntity {
let id: UUID
let name: LocalizedStringResource
static var typeDisplayName: LocalizedStringResource = "Meditation Session"
var displayRepresentation: AppIntents.DisplayRepresentation {
DisplayRepresentation(title: name)
}
static var defaultQuery = MeditationSessionQuery()
} Query for entities
// Queries allow the App Intents framework to
// look up your entities by their identifier
struct MeditationSessionQuery: EntityQuery {
func entities(for identifiers: [UUID]) async throws -> [MeditationSession] {
return identifiers.compactMap { SessionManager.session(for: $0) }
}
} Define a parameter
// Adding a parameter to an intent allows you to prompt the user
// to provide a value for the parameter
struct StartMeditationIntent: AppIntent {
(title: "Session Type")
var sessionType: SessionType?
// ...
} Prompt for values
// Prompting for values can be done by calling methods
// on the property's wrapper type.
func perform() async throws -> some ProvidesDialog {
let sessionToRun = self.session ?? try await $session.requestDisambiguation(
among: SessionManager.allSessions,
dialog: IntentDialog("What session would you like?")
)
}
await MeditationService.start(session: sessionToRun)
return .result(
dialog: "Okay, starting a \(sessionToRun.name) meditation session."
)
} Implement suggestedEntities()
// Queries can provide suggested values for your Entity
// that serve as parameters for App Shortcuts
struct MeditationSessionQuery: EntityQuery {
func entities(for identifiers: [UUID]) async throws -> [MeditationSession] {
return identifiers.compactMap { SessionManager.session(for: $0) }
}
func suggestedEntities() async throws -> [MeditationSession] {
return SessionManager.allSessions
}
} Update App Shortcut parameters
// Your app must notify App Intents when your values change
// This is typically best done in your app’s model layer
class SessionModel {
var sessions: [MeditationSession] = []
private var cancellable: AnyCancellable?
init() {
self.cancellable = $sessions.sink { _ in
MeditationShortcuts.updateAppShortcutParameters()
}
}
// ...
} Add parameterized phrases
// Phrases can also contain a single parameter reference
import AppIntents
struct MeditationShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: StartMeditationIntent(),
phrases: [
"Start a \(.applicationName)",
"Begin \(.applicationName)",
"Meditate with \(.applicationName)",
"Start a \(\.$session) session with \(.applicationName)",
"Begin a \(\.$session) session with \(.applicationName)",
"Meditate on \(\.$session) with \(.applicationName)"
]
)
}
} Resources
Related sessions
-
31 min -
20 min