View in English

  • Global Nav Open Menu Global Nav Close Menu
  • Apple Developer
Search
Cancel
  • Apple Developer
  • News
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
Only search within “”

Quick Links

5 Quick Links

Vidéos

Ouvrir le menu Fermer le menu
  • Collections
  • Sujets
  • Toutes les vidéos
  • À propos

Retour à WWDC25

  • À propos
  • Résumé
  • Transcription
  • Code
  • 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

    • Accelerating app interactions with App Intents
    • Adopting App Intents to support system experiences
    • App intent domains
    • App Intents
    • App Shortcuts
    • Building a workout app for iPhone and iPad
    • Creating your first app intent
    • Integrating actions with Siri and Apple Intelligence
    • Making actions and content discoverable and widely available
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC25

    • Concevoir des extraits interactifs
    • Développez pour Raccourcis et Spotlight avec App Intents

    WWDC24

    • Bring your app to Siri
    • Bring your app’s core features to users with App Intents
    • Design App Intents for system experiences
    • What’s new in App Intents
  • Rechercher dans cette vidéo…

    Bonjour, je m’appelle James, responsable ingénierie dans l’équipe Swift Intelligence Frameworks. Je vous présente App Intents, un framework qui permet d’étendre la découvrabilité, la visibilité et les capacités de votre app à l’ensemble du système et sur toutes les plates-formes Apple. Parlons d’abord du rôle de plus en plus important d’App Intents dans l’écosystème de développement Apple.

    Ensuite, voyons comment utiliser le framework pour rendre les actions et les entités de votre app disponibles dans tout le système. Enfin, notons quelques détails importants que vous devez connaître sur App Intents.

    Mais d’abord, examinons le « pourquoi ». App Intents est plus qu’un framework inséré DANS votre application pour créer des fonctionnalités. C’est un écosystème qui permet aux fonctionnalités de votre app de s’ÉTENDRE à l’ensemble du système.

    App Intents vous permet d’offrir à vos utilisateurs des résultats personnalisés dans Spotlight, des expériences contextuelles pour le bouton Action, configurabilité et interactivité dans les widgets, des commandes faciles d’accès dans le Centre de contrôle et même des actions personnalisées pour Apple Pencil Pro.

    Spotlight peut désormais appeler les actions de votre app de n’importe où sur le Mac.

    Le framework App Intents vous permet de proposer ces expériences enrichies à vos clients, même lorsqu’ils ne sont pas dans votre app. Tout commence par les actions que votre app peut effectuer, comme ouvrir une note, démarrer un entraînement ou ajouter un article à une liste de courses. Ce sont les verbes de votre app et, vous l’avez deviné, vous les décrivez en créant des App Intents, ou intents en bref. Avec une intent, vous fournissez au système des informations supplémentaires pour effectuer correctement l’action. Les intents acceptent des paramètres et renvoient des valeurs. Ces entrées et sorties peuvent être des types Swift natifs ou des types que vous définissez dans votre app. Vous pouvez créer deux types de valeurs avec App Intents. Utilisez une AppEnum pour vos types avec des valeurs fixes, et une AppEntity pour les types dynamiques. Les AppEnum et AppEntity sont les noms de votre app. Les Raccourcis d’app vous permettent d’améliorer vos intents clés et de les rendre plus accessibles et plus faciles à détecter. Les Raccourcis d’apps apparaissent lors d’une recherche dans Spotlight, avec Siri, la configuration du Bouton Action, etc. Vous pouvez les considérer comme les phrases de votre app, faites à partir d’une intent et de tous les paramètres dont elle a besoin pour s’exécuter. La meilleure façon d’apprendre, c’est de faire. Voyons ce qu’il faut pour créer ma première intent. J’adore voyager et je développe une app qui recense les monuments célèbres à travers le monde. Mon app comporte plusieurs sections. Je peux faire défiler une liste de monuments célèbres, les consulter sur une carte ou afficher les collections que j’ai créées. Les utilisateurs aiment faire défiler la grille de monuments. Je crée un App Intent qui facilite la navigation directe vers cette partie de l’app. Comment je fais cela ? Je définis une nouvelle structure qui adopte le protocole App Intents. Les exigences minimales pour un App Intent sont un titre et une méthode perform.

    Le titre est une chaîne unique et localisée qui apparaît comme nom de l’intent. La méthode perform contient la logique de l’intent. J’utilise un navigateur partagé pour ouvrir la vue des Monuments. La navigation doit être effectuée sur le thread principal, je vais donc marquer perform avec @MainActor.

    La méthode perform retourne un IntentResult. Les IntentResults peuvent contenir un certain nombre d’éléments, notamment une boîte de dialogue que Siri peut énoncer et un extrait de vue à afficher. Par défaut, exécuter une intent ne met pas votre app au premier plan, et fournir une boîte de dialogue et un extrait de code est un excellent moyen de montrer le résultat de votre action.

    cette intent est conçue pour parcourir les écrans de l’app, je vais donc la configurer pour qu’elle s’ouvre lorsqu’elle est exécutée. Je définis la nouvelle propriété supportedModes sur foreground pour ouvrir mon app avant que l’intent ne soit exécutée, et c’est tout ce qu’il faut pour créer ma première intent. Après avoir installé mon app, les intents se trouvent dans Raccourcis. Je peux créer un nouveau Raccourci et ajouter mon intent de navigation. L’exécuter met mon app au premier plan et m’amène directement à la vue Monuments. Mon app comporte également des sections pour visualiser les collections et afficher les monuments sur une carte. Ce serait génial si l’intent pouvait également naviguer vers ces parties de l’app. Mon app utilise une simple Swift enum pour modéliser les sections. Pour rendre le type compatible avec le framework, j’adopte le protocole AppEnum. Les App Enums ont peu d’exigences. Ils doivent être instanciables à partir d’une chaîne, j’ajoute donc une valeur brute String. TypeDisplayRepresentation décrit le type dans son ensemble et une représentation caseDisplayRepresentation décrit chaque cas de l’enum.

    Ces représentations doivent être des valeurs constantes, car ces informations sont utilisées au moment de la compilation.

    Dans mon intent, j’ajoute une nouvelle variable pour contenir l’option de navigation. J’ajoute l’attribut @Parameter pour en faire un paramètre d’intent. Les paramètres d’intent agissent comme des entrées pour les intents. Ils peuvent être obligatoires ou facultatifs. J’ai rendu cela obligatoire, donc le runtime s’assurera qu’il a une valeur avant que perform ne soit appelé.

    Je mets à jour la méthode perform pour utiliser l’option de navigation résolue et modifier le titre pour refléter la nouvelle action.

    Retour à mon Raccourci, je vois maintenant l’option de navigation comme paramètre modifiable. Lorsque j’exécute l’intent, Raccourcis invite à choisir une section. Je choisis Carte et j’accède directement à cette vue. Les types du framework App Intents sont conçus pour être hautement personnalisables. Cela vous permet de mettre rapidement en place les éléments de base, puis d’affiner l’expérience. J’ajoute quelques informations supplémentaires à l’intent, ce qui la rend encore meilleure à utiliser.

    Par défaut, les Raccourcis affichent chaque paramètre sous forme de ligne. Touchez la ligne pour afficher une liste de valeurs pour ce type. C’est bien, mais je peux affiner l’expérience.

    Une App Enum ne nécessite qu’un titre pour chaque cas d’énumération, mais peut être configurée avec des infos supplémentaires, telles qu’une icône.

    Pour ajouter une icône, je dois utiliser l’initialiseur DisplayRepresentation. Je peux ensuite ajouter un symbole pour chaque cas. Une fois que j’ai fait cela, Raccourcis affiche l’image dans le sélecteur. Les intents peuvent être configurées à l’aide d’une représentation fluide de type phrase, appelée résumé des paramètres. Un parameterSummary décrit l’action et ses paramètres d’une manière lisible par l’homme.

    Je fournis le résumé avec mon paramètre interpolé dans la chaîne. Les Raccourcis affichent le résumé avec le paramètre sélectionnable en ligne, fournissant une description plus utile de l’action.

    En fait, cela ne se lit pas encore comme une phrase. Je peux résoudre ce problème en ajoutant un titre personnalisé à mon paramètre.

    Et tant qu’à faire, une boîte de dialogue personnalisée à afficher lors de la demande d’une valeur. Une autre nouveauté : lorsque vous mettez en œuvre un résumé des paramètres pour votre intent qui inclut tous les paramètres requis, les utilisateurs peuvent exécuter votre action depuis Spotlight sur le Mac. Pour découvrir les nouveautés de Spotlight, je vous conseille de regarder cette session.

    En modélisant les actions de votre app en tant qu’intents, vos clients peuvent créer des raccourcis et des automatisations puissants. Toutefois, certaines intents sont si vitales pour votre app qu’elles doivent être disponibles au moment de l’installation. Vous pouvez les fournir en adoptant les Raccourcis d’app.

    Un Raccourci d’app est un type qui expose automatiquement un App Intent dans tout le système. Les Raccourcis d’apps sont mis en avant lors d’une recherche dans Spotlight. Les utilisateurs peuvent utiliser Siri pour exécuter un Raccourci d’app en prononçant l’une de leurs phrases déclencheur. Ils peuvent être configurés pour s’exécuter à partir du Bouton Action ou de la pression de l’Apple Pencil. Les Raccourcis d’app s’affichent dans l’app Raccourcis sans aucune configuration de l’utilisateur et encore mieux : ils ne nécessitent que quelques lignes de code pour être construits. Regardons comment.

    Les apps fournissent des Raccourcis d’app par l’intermédiaire du AppShortcutsProvider. Votre app doit définir un fournisseur unique, contenant tous vos Raccourcis d’app. Un Raccourci d’app prend une occurrence d’une intent ainsi qu’une liste de phrases, un titre et une image. Les phrases d’un Raccourci d’app peuvent être prononcées ou tapées à Siri pour l’exécuter. Chaque phrase doit inclure l’espace réservé applicationName. Les phrases peuvent inclure jusqu’à un paramètre d’intent. S’il est fourni, un Raccourci d’app sera créé pour chaque valeur de ce type.

    Cette structure simple est tout ce qu’il faut pour créer un Raccourci d’app. Les Raccourcis affichent les Raccourcis d’app de votre app dans une nouvelle section. Les phrases influencent les Raccourcis d’app créés. Si vous fournissez une phrase sans paramètre, un Raccourci d’app est créé en utilisant le titre et le nom de l’image. Puisque j’ai fourni une phrase avec une App Enum, un Raccourci d’app est créé pour chaque cas.

    Je peux désormais exécuter mon intent avec Siri ou Spotlight. Les Raccourcis d’app sont un excellent moyen de rendre vos intents détectables. Pour en savoir plus sur la création de Raccourcis d’app, visionnez cette séance de la WWDC23.

    Les monuments sont un concept central de mon app. Ce serait génial de pouvoir agir dessus à partir de mes intents. Contrairement à la liste constante des options de navigation, les monuments sont dynamiques, je ne peux donc pas utiliser d’AppEnum. Je vais plutôt créer une AppEntity pour modéliser mes monuments.

    Mon app a déjà un type de monument. Bien que je puisse conformer ce type à AppEntity, dans ce cas, je vais créer une nouvelle structure LandmarkEntity. Ce type fera le pont entre les App Intents et mon modèle de données sous-jacent.

    AppEntity doit être identifiable, j’ajoute donc un id. Il est important que cet identifiant soit persistant et que vous puissiez l’utiliser pour rechercher des instances de votre entité. Nous y reviendrons. Comme une intent peut avoir des paramètres, les entités peuvent avoir des propriétés désignées par l’attribut @Property. Elles sont exposées à vos clients dans Raccourcis et peuvent être utilisées dans les actions Rechercher et Filtrer. Je pouvais définir ces valeurs à partir de mon modèle de données, mais désormais, je peux ajouter des Getters aux propriétés de mon entité, à l’aide du nouvel attribut @ComputedProperty. Au lieu de copier des valeurs entre ces types, je peux m’en remettre à mon modèle de données. Comme pour AppEnum, AppEntity nécessite une représentation pour le type et les instances du type.

    AppEntity nécessite une information supplémentaire, appelée requête.

    Contrairement à une AppEnum qui a un ensemble connu de valeurs, les AppEntities sont dynamiques. Mon app peut avoir n’importe quel nombre de monuments. Les requêtes sont la façon dont le système peut raisonner avec mes entités. Il le fait en répondant à plusieurs questions différentes. Le premier type de question est : « Quelles sont les entités existantes ? » La requête est chargée de répondre à cette question et de renvoyer une collection d’entités correspondantes.

    Les requêtes prennent en charge de nombreux types de questions de ce type. Par exemple, une requête de chaîne d’entités pose la question suivante : « Avez-vous des entités correspondant à cette chaîne ? ». Une requête de propriété d’entité peut demander : « Quels sont tous les monuments de cet état ? ». Toutes les requêtes doivent répondre à une question très précise : « Quelle est l’entité de cet identifiant ? ». Cela permet au système de référencer une entité de manière unique et de ne la résoudre que lorsque cela est nécessaire. Je peux fournir la requête en créant un type conforme au protocole EntityQuery. La méthode entities(for:) est la façon dont les requêtes répondent à la question « Quelle entité a cet ID ? ». Elle prend un tableau d’identifiants et renvoie un tableau d’instances d’entité. Nous reviendrons plus tard sur la question « Quelles sont les entités existantes ? ». Les requêtes ont souvent besoin d’accéder à une base de données locale ou à une autre dépendance pour récupérer les instances. Je peux utiliser l’attribut @Dependency pour injecter des dépendances dans ma requête. Je dois enregistrer ma dépendance à l’aide du AppDependencyManager partagé. Vous devez enregistrer les dépendances le plus tôt possible dans le cycle de vie de votre app. Maintenant que j’ai créé une AppEntity Landmark, je peux l’utiliser à partir de mes intents. Quand je voyage, j’aimerais savoir quel monument est le plus proche de moi. Je crée une App Intent pour me le montrer. Je commence par une intent de base Monument le plus proche. Je dois extraire le monument le plus proche de mon modèle de données. Les dépendances sont également prises en charge dans les intents, je peux donc ajouter ma dépendance. Pour ma méthode perform, j’ajoute une ReturnsValue de LandmarkEntity. Les types utilisés comme paramètres d’intent peuvent également être renvoyés à partir d’une intent. Une valeur renvoyée peut être utilisée comme entrée pour une autre intent, par exemple, dans un Raccourci en plusieurs étapes. Je renvoie également une boîte de dialogue et un extrait de vue. Cela permet à mon intent de montrer ou de dire son résultat. Enfin, je peux mettre en œuvre ma méthode perform. Après avoir trouvé le monument le plus proche, je renvoie un résultat contenant l’entité, la boîte de dialogue et la vue. En fournissant à la fois une boîte de dialogue et une vue, je m’assure que mes clients peuvent toujours trouver leur monument le plus proche, quelle que soit la façon dont l’intent est invoquée. À propos, créer un Raccourci d’app pour cette intent rendra son exécution encore plus facile. Mes clients peuvent désormais utiliser Siri ou Spotlight pour accéder facilement à cet intent, même si leur téléphone est dans leur poche. Les intents, les entités et les requêtes sont les éléments constitutifs d’App Intents. Chaque protocole dispose de sous-protocoles et de configurations que vous pouvez utiliser pour fournir des fonctionnalités supplémentaires. Voyons comment je peux affiner mon AppEntity pour offrir des expériences supplémentaires. J’aimerais pouvoir visualiser facilement mon monument le plus proche. Je peux utiliser l’app Raccourcis pour m’aider. Je commence par créer un Raccourci et ajouter l’intent Trouver le monument le plus proche. Pour extraire les résultats, j’ajoute une action Afficher le contenu. Cela prend le résultat de mon intent et le restitue. Par défaut, cette action affiche la représentation d’affichage de l’entité Landmark, mais je peux choisir n’importe quelle propriété d’entité à restituer.

    L’entité Landmark ne détient pas directement une image, mais elle dispose d’un chemin d’accès à l’image. Je peux utiliser le protocole Transferable pour déclarer une représentation d’image pour l’entité. Transferable est un moyen déclaratif de décrire différentes représentations de données pour un type. Ces représentations peuvent être utilisées pour partager des données entre apps. Je fournis les données d’image dans le cadre de la représentation de TransferRepresentation. De retour dans Raccourcis, je peux maintenant choisir d’afficher la représentation image de l’entité. L’exécution de mon Raccourci affiche l’image du monument. Déclarer une représentation d’image présente des avantages supplémentaires. Je peux utiliser cette valeur d’image comme entrée pour toute action qui prend une photo, même celles d’autres apps. Pour en savoir plus sur Transferable, consultez ces sessions.

    J’aimerais apporter un changement supplémentaire à mon entité pour la rendre plus facile à trouver dans le système. Spotlight propose une recherche sémantique puissante entre les applications. Ajouter des entités à Spotlight permet au système de mieux comprendre votre contenu. Pour que Spotlight indexe mon entité, je peux adopter le protocole IndexedEntity. Une IndexedEntity est une AppEntity qui inclut un jeu d’attributs Spotlight de base.

    Désormais, vous pouvez ajouter des clés d’indexation Spotlight directement sur les propriétés. L’annotation des propriétés permet à Spotlight d’afficher des informations plus pertinentes pour les clients. Lorsque vous faites don d’entités indexées, le framework gère la création de l’élément et de l’ensemble d’attributs pouvant faire l’objet d’une recherche pour vous. Une fois les entités données, elles peuvent être trouvées dans Spotlight. Par défaut, toucher sur une entité met l’app au premier plan. Je peux rendre cette expérience encore meilleure et ouvrir directement la vue détaillée du monument. Je commence par créer une intent conforme au protocole OpenIntent. Les intents adoptant ce protocole ouvrent automatiquement l’app avant qu’elles ne soient effectuées, ce qui me permet d’ignorer l’ajout d’un mode pris en charge. OpenIntent doit avoir un paramètre cible. Lorsque vous appuyez sur une entité dans Spotlight, une intent ouverte correspondante s’exécute, s’il y en a une.

    Au lieu d’appeler mon navigateur, je peux maintenant adopter le nouveau protocole TargetContentProvidingIntent, conçu spécifiquement pour la navigation. Ces intents ne nécessitent pas de méthode perform. Au lieu de cela, je peux attacher un modificateur onAppIntentExecution à ma vue. Dans la fermeture, je peux utiliser le paramètre de l’intent pour effectuer une navigation SwiftUI.

    Désormais, lorsque je touche sur un monument dans Spotlight, j’accède directement à sa vue détaillée. J’aimerais conclure cette section en parlant un peu plus des requêtes et de la façon dont elles fournissent des entités. Pour voir cela en action, je crée un nouveau Raccourci d’app pour ouvrir un monument. J’ai ajouté un nouveau Raccourci d’app à mon fournisseur avec deux phrases. L’un avec un paramètre de monument et l’autre sans. Cependant, l’exécution de mon Raccourci d’app ne me donne aucun monument à choisir. Vous l’aurez deviné, je peux utiliser la requête pour fournir quelques monuments. Je mets en œuvre la méthode facultative suggestedEntities sur EntityQuery, en renvoyant les monuments préférés de mon client. Maintenant, lorsque j’exécute à nouveau l’intent, la liste des entités suggérées m’est présentée. Les entités suggérées ont également une autre utilisation. Rappelez-vous quand j’ai ajouté une phrase paramétrée pour cette intent. Je peux générer un Raccourci d’app pour chaque entité suggérée en appelant la méthode updateAppShortcutParameters sur mon fournisseur. Je peux désormais utiliser Siri et Raccourcis pour accéder directement à mes monuments préférés. Les requêtes peuvent répondre à plusieurs autres questions concernant vos entités. Si vos entités peuvent toutes tenir en mémoire, vous pouvez utiliser une requête d’entité énumérable pour les renvoyer toutes. Les App Intents peuvent dériver les requêtes les plus compliquées de celle-ci. Une EntityPropertyQuery ajoute la possibilité de renvoyer une liste triée d’entités, à partir d’un ensemble de prédicats. Dans mon cas, j’implémente EntityStringQuery pour prendre en charge la recherche d’entités à partir d’une chaîne. Je renvoie une liste de monuments où la chaîne correspond à leur nom ou à leur description. Les clients peuvent désormais rechercher tous les monuments lors de la configuration d’une intent qui a besoin d’un monument. Nous n’avons fait qu’effleurer la surface du framework App Intents et de ses nombreuses fonctionnalités. Consultez la documentation d’App Intents pour découvrir toutes les façons dont vous pouvez utiliser le framework pour ravir vos utilisateurs. J’aimerais terminer en vous donnant un aperçu de l’architecture qui sous-tend App Intents. Lorsque vous compilez votre app avec App Intents, votre code est la source de vérité. Les App Intents ne nécessitent aucun fichier d’installation ou de configuration. Votre code source Swift est lu au moment de la compilation pour générer sa représentation d’App Intents. Cette représentation est stockée dans votre app ou votre framework. Une fois votre app installée, le système utilise ces données pour comprendre ses fonctionnalités sans avoir besoin de l’exécuter. Jetons un coup d’œil à une intent pour voir comment cela fonctionne. Le nom de l’intent devient l’identifiant unique de l’action. Le titre d’une intent aide les utilisateurs à différencier les intents, et la signature de retour de la méthode perform décrit comment afficher le résultat de l’intent. Ce processus s’effectuant au moment de la compilation, plutôt qu’au moment de l’exécution, certaines valeurs doivent être fournies avec des valeurs constantes. Par exemple, le titre d’une intent doit être constant. L’appel à une fonction ou à une propriété calculée entraîne une erreur. Ce traitement s’effectue individuellement pour chaque cible de votre app. Afin de bien répartir vos types d’App Intent entre les cibles, tenez compte de quelques points supplémentaires. L’année dernière, nous avons introduit la possibilité pour votre app et vos extensions App Intents de faire référence à des types d’App Intent définis dans un framework. Cette année, nous sommes ravis d’annoncer que vous pouvez désormais ajouter App Intents à vos paquets Swift et à vos bibliothèques statiques. Lorsque vous utilisez des types d’App Intent sur plusieurs cibles, vous devez fournir au runtime des infos supplémentaires sur chaque cible. Cela garantit que vos types sont correctement indexés et validés. Examinons comment cela se fait. Mon app n’a qu’une seule cible contenant tout mon code App Intents. Je veux introduire une nouvelle extension App Intents pour héberger certaines de mes intents. Les deux cibles ont besoin d’accéder à Landmarks. Je crée donc un package Swift et j’y déplace LandmarkEntity. Pour partager les types entre les cibles, je dois enregistrer chaque cible en tant que AppIntentsPackage. Je crée d’abord un AppIntentsPackage dans la même cible que l’entité. J’ajoute un autre AppIntentsPackage à ma cible d’app. Je peux fournir une liste des packages inclus, donc j’inclus celui que je viens de créer. Enfin, je fais de même à partir de mon extension. Cela garantit que le runtime App Intents dispose d’un accès approprié à tous les types définis dans le package. Vous devez utiliser un AppIntentsPackage lorsque vous référencez du code qui n’a pas été compilé dans une bibliothèque statique.

    Il est temps de conclure cette session. Si c’était votre premier aperçu d’App Intents, commencez petit en ajoutant le premier Raccourci d’app à votre app. À partir de là, explorez le framework pour déterminer quelles fonctionnalités peuvent apporter le plus de valeur à vos clients. Pour en savoir plus sur App Intent, nous avons d’autres séances intéressantes cette année. Merci de votre attention !

    • 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.

Developer Footer

  • Vidéos
  • WWDC25
  • Apprenez à connaître App Intents
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • App Store
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Fonts
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Open Source
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Sample Code
    • Tutorials
    • Downloads
    • Forums
    • Videos
    Open Menu Close Menu
    • Support Articles
    • Contact Us
    • Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Get the Apple Developer app.
    Copyright © 2025 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines