-
Apprenez à connaître App Intents
Découvrez le framework App Intents et son rôle de plus en plus important au sein des plates-formes de développement d'Apple. Nous vous présenterons les concepts de base : intents, entités, requêtes et bien plus encore. Vous apprendrez comment ces éléments s'emboîtent et vous permettent d'intégrer votre app sur les appareils Apple, des fonctionnalités logicielles comme Spotlight et Raccourcis aux fonctionnalités matérielles comme le bouton Action. Nous expliquerons également comment App Intents est la passerelle de votre app vers l'intégration avec Apple Intelligence à l'avenir.
Chapitres
- 0:00 - Introduction
- 0:45 - Écosystème App Intents
- 2:47 - Naviguer dans le framework
- 21:15 - Fonctionnement
Ressources
- Adopting App Intents to support system experiences
- Building a workout app for iPhone and iPad
- Accelerating app interactions with App Intents
- App intent domains
- Creating your first app intent
- Integrating actions with Siri and Apple Intelligence
- Making actions and content discoverable and widely available
- App Shortcuts
- App Intents
Vidéos connexes
WWDC25
WWDC24
-
Rechercher dans cette vidéo…
-
-
3:23 - Navigate Intent
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() } } -
5:02 - Navigation Option App Enum
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" ] } -
5:38 - Navigate Intent with Parameter
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() } } -
6:57 - Case Display Representations with Images
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") ) ] -
7:28 - Navigation Option With Parameter Summary
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() } } -
9:22 - App Shortcuts Provider and Navigation Intent App Shortcut
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" ) } } -
11:02 - Landmark Entity
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() } -
13:19 - Landmark Entity Query
struct LandmarkEntityQuery: EntityQuery { @Dependency var modelData: ModelData func entities(for identifiers: [LandmarkEntity.ID]) async throws -> [LandmarkEntity] { modelData .landmarks(for: identifiers) .map(LandmarkEntity.init) } } -
13:50 - App Dependency Manager
@main struct LandmarksApp: App { init() { AppDependencyManager.shared.add { ModelData() } } } -
14:18 - Closest Landmark Intent
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) ) } } -
15:18 - Closest Landmark App Shortcut
AppShortcut( intent: ClosestLandmarkIntent(), phrases: [ "Find closest landmark in \(.applicationName)" ], shortTitle: "Closest landmark", systemImageName: "location" ) -
16:33 - Transferable
extension LandmarkEntity: Transferable { static var transferRepresentation: some TransferRepresentation { DataRepresentation(exportedContentType: .image) { return try $0.imageRepresentationData } } } -
17:31 - Indexed Entity
struct LandmarkEntity: IndexedEntity { // ... @Property( indexingKey: \.displayName ) var name: String @Property( indexingKey: \.contentDescription ) var description: String } -
18:17 - Open Landmark Intent
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) } } } -
19:24 - Open Landmark App Shortcut
AppShortcut( intent: OpenLandmarkIntent(), phrases: [ "Open \(\.$target) in \(.applicationName)", "Open landmark in \(.applicationName)" ], shortTitle: "Open", systemImageName: "building.columns" ) -
19:39 - Suggested Entities
struct LandmarkEntityQuery: EntityQuery { // ... func suggestedEntities() async throws -> [LandmarkEntity] { modelData .favoriteLandmarks() .map(LandmarkEntity.init) } } -
20:06 - Update App Shortcut Parameters
TravelTrackingAppShortcuts.updateAppShortcutParameters() -
20:25 - EnumerableEntityQuery
extension LandmarkEntityQuery: EnumerableEntityQuery { func allEntities() async throws -> [LandmarkEntity] { // ... } } -
20:36 - EntityPropertyQuery
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] { // ... } } -
20:44 - EntityStringQuery
extension LandmarkEntityQuery: EntityStringQuery { func entities(matching: String) async throws -> [LandmarkEntity] { modelData .landmarks .filter { $0.name.contains(matching) || $0.description.contains(matching) } .map(LandmarkEntity.init) } } -
23:10 - App Intents Package
// 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 {}
-
-
- 0:00 - Introduction
Découvrez App Intents, un framework qui permet d’améliorer la visibilité et les fonctionnalités des apps sur toutes les plateformes Apple. Les sujets abordés incluent l’importance du framework, sa mise en œuvre et les bonnes pratiques en matière d’écriture d’App Intents.
- 0:45 - Écosystème App Intents
App Intents est un écosystème qui permet aux apps d’étendre leurs fonctionnalités à l’ensemble du système, Spotlight, le bouton Action, les widgets, le centre de contrôle et l’Apple Pencil Pro. Les utilisateurs peuvent effectuer des actions depuis n’importe où, même lorsqu’ils ne sont pas dans l’app. Vous définissez les actions de l’app comme des intents, qui peuvent utiliser des paramètres pour renvoyer des valeurs, à l’aide d’AppEnum pour les constantes ou d’AppEntity pour les polices dynamiques. Les Raccourcis d’app, créés à partir d’intents et de paramètres, améliorent l’accessibilité et la visibilité via Spotlight, Siri et le bouton Action.
- 2:47 - Naviguer dans le framework
L’app fournie en exemple explore des points de repère célèbres dans le monde entier. Pour améliorer l’expérience utilisateur, elle met en œuvre les App Intents, qui permettent d’effectuer des actions directement depuis Siri, Raccourcis et Spotlight. Le processus implique de définir des structs qui adoptent le protocole App Intents, en spécifiant des titres, des méthodes d’exécution et des résultats d’intent. Vous ajoutez des paramètres aux intents, ce qui permet aux utilisateurs de choisir des sections spécifiques de l’app, telles que la grille des points de repère ou la vue cartographique. Pour rendre l’app plus facile à découvrir et à utiliser, vous créez des raccourcis d’app, qui exposent automatiquement les intents dans tout le système. Ils modélisent également des données dynamiques telles que des points de repère à l’aide d’entités d’app, ce qui permet aux personnes d’agir par rapport à des points de repère spécifiques par le biais d’intents. Dans le framework App Intents, les entités d’app représentent des données dynamiques telles que des points de repère. Les requêtes sont des composants essentiels qui permettent au système de traiter ces entités. Elles répondent à diverses questions, notamment la récupération de toutes les entités, la mise en correspondance de chaînes ou de propriétés spécifiques et le référencement unique d’entités par ID. Vous pouvez personnaliser les requêtes à l’aide de différents types, tels que EntityStringQuery et EntityPropertyQuery, et ces requêtes peuvent dépendre de bases de données locales ou d’autres ressources. Les dépendances peuvent être injectées dans les requêtes à l’aide de l’attribut « @Dependency ». Enregistrez les dépendances le plus tôt possible dans le cycle de vie de l’app. À l’aide des App Intents, vous pouvez créer des actions personnalisées qui peuvent être exécutées via Siri, Spotlight ou Raccourcis. En renvoyant des types d’entités à partir d’intents, ces actions peuvent être liées ensemble dans des Raccourcis en plusieurs étapes. Pour améliorer l’expérience utilisateur, vous pouvez rendre les entités transférables, ce qui permet de les partager entre les apps. L’adoption du protocole Indexed Entity permet à Spotlight d’effectuer des recherches sémantiques. Vous pouvez également créer des Intents ouvertes pour accéder directement à des vues spécifiques au sein de l’app lorsque des entités sont touchées dans Spotlight.
- 21:15 - Fonctionnement
App Intents utilise le code source Swift au moment de la compilation de la build pour générer une représentation App Intents, qui est ensuite stockée dans l’app ou le framework. Cela permet au système de comprendre les fonctionnalités de l’app sans l’exécuter. Le nom de l’Intent sert d’identifiant unique ; le titre aide les gens à différencier les intents, et la signature de retour de la méthode « perform » définit le rendu du résultat. Vous devez fournir des valeurs constantes pour certaines propriétés d’Intent, car le traitement a lieu au moment de la compilation de la build. Pour partager les types d’App Intent entre des cibles, telles qu’une app et son extension, vous pouvez utiliser des paquets Swift ou des bibliothèques statiques. Vous devez enregistrer chaque cible en tant que paquet App Intents pour garantir l’indexation et la validation correctes des types partagés via l’exécution d’App Intents.