← Tous les articles

La surface des widgets d'iOS 26 : un seul App Intent, de nombreux emplacements

Pendant des années, un widget n’était qu’un instantané. Le système affichait votre vue sur une chronologie, l’utilisateur la regardait, et le moindre appui ouvrait l’application. Ce modèle a disparu. Depuis iOS 17, un widget peut comporter des boutons et des interrupteurs qui exécutent du code sans rien lancer, et le code qu’ils exécutent est un App Intent1. Il en va de même pour les commandes du centre de contrôle et pour les boutons d’une activité en direct. Une fois que l’on a saisi cela, la surface des widgets d’iOS 26 cesse de ressembler à trois API distinctes pour n’en former plus qu’une seule : un ensemble d’emplacements où le système affichera vos App Intents, chacun avec son espace propre et la même tuyauterie en dessous.

C’est tout l’enjeu de cet article. Apprenez l’App Intent une bonne fois et vous illuminez l’écran d’accueil, l’écran verrouillé, le centre de contrôle, le bouton Action, la Dynamic Island et (le même intent, encore) Siri et Apple Intelligence. Écrivez trois fonctionnalités déconnectées et vous fournissez quatre fois plus d’efforts pour un résultat moins bon.

En bref

  • Widgets interactifs (iOS 17 et ultérieur) : placez un Button(intent:) ou un Toggle(isOn:intent:) dans la vue d’un widget ; le système exécute le perform() de l’App Intent dans votre extension de widget, hors de l’application, puis recharge la chronologie1.
  • Commandes du centre de contrôle (iOS 18 et ultérieur) : un ControlWidget construit à partir d’un ControlWidgetButton ou d’un ControlWidgetToggle, adossé aux mêmes App Intents, apparaît dans le centre de contrôle, sur l’écran verrouillé et sur le bouton Action2.
  • Activités en direct (ActivityKit) : un ActivityAttributes et une ActivityConfiguration pilotent l’écran verrouillé et la Dynamic Island ; les mises à jour pilotées par serveur arrivent par notification push, et les boutons à l’intérieur sont eux aussi des App Intents3.
  • iOS 26 ajoute le rendu, pas le modèle : les widgets adoptent la présentation Liquid Glass et des modes de rendu accentués, mais l’architecture des App Intents comme surface est inchangée depuis iOS 184.
  • Le fait unificateur : un bouton de widget, une commande, une phrase Siri et une action Apple Intelligence peuvent tous être le même App Intent. Concevez la capacité une seule fois.

Widgets interactifs : le bouton qui n’ouvre pas l’application

Le mécanisme est simple et mérite d’être énoncé précisément. Vous ajoutez un Button ou un Toggle SwiftUI à la vue d’un widget, mais au lieu d’une closure d’action, vous passez un App Intent1 :

struct WaterWidgetView: View {
    let logged: Int

    var body: some View {
        VStack {
            Text("\(logged) glasses")
            Button(intent: LogWaterIntent()) {
                Label("Add", systemImage: "plus")
            }
        }
    }
}

Lorsque l’utilisateur appuie, le système exécute LogWaterIntent.perform() à l’intérieur de votre extension de widget. L’application ne se lance pas. L’intent fait son travail (écrire dans le stockage partagé, mettre à jour un compteur), et la chronologie du widget se recharge pour afficher le résultat.

Un Toggle fonctionne de la même manière, à travers un SetValueIntent, qui reçoit la nouvelle valeur activé/désactivé que l’utilisateur vient de définir :

struct ToggleReminderIntent: SetValueIntent {
    static let title: LocalizedStringResource = "Toggle Reminder"

    @Parameter(title: "Enabled")
    var value: Bool

    func perform() async throws -> some IntentResult {
        ReminderStore.shared.enabled = value
        return .result()
    }
}

Le widget lie Toggle(isOn: store.enabled, intent: ToggleReminderIntent()), le système attribue à value le nouvel état, exécute perform() et recharge. Même forme que le bouton, un paramètre de plus1.

Deux contraintes définissent ce que vous pouvez faire ici, et toutes deux sont faciles à enfreindre. Premièrement, perform() s’exécute dans l’environnement contraint de l’extension de widget, avec un budget d’exécution serré ; il est fait pour un changement d’état rapide, pas pour un envoi réseau ou un calcul lourd. Deuxièmement, le widget reflète un état, il n’anime pas une interface arbitraire. Vous modifiez des données et la chronologie se réaffiche ; vous n’exécutez pas de transition personnalisée. Concevez l’interaction comme « changer une valeur, afficher la nouvelle valeur » et tout fonctionne. Visez davantage et le système vous résistera.

Commandes du centre de contrôle : le même intent, une autre pièce

iOS 18 a ouvert le centre de contrôle, l’écran verrouillé et le bouton Action aux commandes tierces, et l’API est délibérément parallèle à celle des widgets2. Une commande est un ControlWidget, et son corps est un ControlWidgetButton ou un ControlWidgetToggle câblé à un App Intent :

struct LogWaterControl: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlConfiguration(kind: "com.example.logWater") {
            ControlWidgetButton(action: LogWaterIntent()) {
                Label("Log Water", systemImage: "drop.fill")
            }
        }
    }
}

Si LogWaterIntent alimente déjà votre widget interactif, la commande est presque gratuite : même intent, nouvelle enveloppe. C’est l’architecture qui porte ses fruits. La commande n’est pas une seconde implémentation de la fonctionnalité ; c’est un second point de montage pour celle que vous avez déjà écrite. Une commande à interrupteur utilise un SetValueIntent exactement comme le fait l’interrupteur d’un widget, de sorte qu’une capacité « couper le son », « démarrer une séance » ou « basculer le mode sombre », construite une seule fois, apparaît dans le centre de contrôle, sur l’écran verrouillé et sur le bouton Action sans aucune logique nouvelle2.

Activités en direct : la surface qui se met à jour elle-même

Les activités en direct sont le troisième emplacement, et celui qui compte le plus de pièces mobiles. Un type ActivityAttributes définit le contenu statique et dynamique, une ActivityConfiguration rend la présentation de l’écran verrouillé et les régions de la Dynamic Island, et ActivityKit démarre, met à jour et termine l’activité3. Les boutons à l’intérieur d’une activité en direct sont, là encore, des App Intents, de sorte qu’une commande « pause » ou « suivant » dans la Dynamic Island exécute le même genre d’intent que le bouton de widget.

L’élément qui fait des activités en direct une discipline à part entière, c’est le chemin de mise à jour. Un minuteur que vous mettez à jour localement est simple. Une activité pilotée par des événements qui se produisent sur un serveur (une livraison qui avance, un score de match qui change) se met à jour par notification push : vous vous inscrivez à pushTokenUpdates, vous envoyez des charges utiles push ActivityKit depuis votre backend, et le système met à jour l’écran verrouillé et la Dynamic Island sans que votre application s’exécute le moins du monde3. C’est véritablement puissant et véritablement facile à rater, car désormais la justesse de votre activité dépend d’un contrat serveur, de la fiabilité des notifications push et d’une politique de date de péremption, et non plus du seul code local.

Ce qu’iOS 26 a réellement changé

Pour les widgets d’iOS 26, le grand titre, c’est la présentation, pas l’architecture. Les widgets adoptent le matériau Liquid Glass et gagnent des modes de rendu accentués, afin de s’accorder au nouveau langage de conception du système et de se teinter correctement dans les contextes où l’OS recolore le contenu4. Cela compte pour l’apparence d’un widget sur l’écran d’accueil, l’écran verrouillé et en mode StandBy, et cela mérite une passe de conception. Cela ne change pas le fonctionnement de l’interactivité. Si vous avez construit des widgets et des commandes interactifs sur iOS 18, le passage à iOS 26 est un rafraîchissement visuel, pas une réécriture. Traitez avec méfiance les affirmations selon lesquelles iOS 26 aurait « introduit » les widgets interactifs : l’interactivité est arrivée avec iOS 17, les commandes avec iOS 18, et iOS 26 leur a donné l’allure du reste du système.

L’implication de conception de Liquid Glass est bien réelle, cependant. Un widget est un contenu que le système compose par-dessus le fond d’écran et réfracte à travers le verre de l’interface, de sorte que les mêmes règles qui régissent Liquid Glass dans une application s’appliquent : respectez la séparation entre couche fonctionnelle et couche de contenu, et ne combattez pas le matériau avec de lourds arrière-plans personnalisés que le verre ne peut pas lire.

L’architecture, énoncée simplement

Voici le modèle qu’il faut garder en tête. Un App Intent est une capacité nommée, typée et décrite. iOS vous offre un éventail croissant d’emplacements où monter cette capacité :

  • Un Button ou un Toggle à l’intérieur d’un widget.
  • Un ControlWidget dans le centre de contrôle, sur l’écran verrouillé et sur le bouton Action.
  • Un bouton à l’intérieur d’une activité en direct et de sa Dynamic Island.
  • Une phrase Siri et une action Shortcuts.
  • Une action qu’Apple Intelligence peut invoquer pour le compte de l’utilisateur5.

Chacun de ces éléments est le même type AppIntent avec une méthode perform(). Le travail consiste à bien concevoir cette capacité : un nom clair, des paramètres typés, un perform() rapide et idempotent, et un résultat sensé. Faites-le une fois et les surfaces ne sont que des enveloppes. C’est le même argument que j’ai défendu à propos des App Intents en tant que véritable API vers votre application et à propos des trois surfaces qu’une application iOS expose désormais : la surface des widgets n’est pas une fonctionnalité que vous construisez, c’est un emplacement où vos capacités apparaissent une fois qu’elles existent.

Quand s’en abstenir

La surface des widgets récompense les applications dotées d’un véritable état consultable d’un coup d’œil et d’actions rapides : un traqueur, un minuteur, un interrupteur, une commande de lecture en cours. Elle ne récompense pas tout.

  • Pas d’état consultable d’un coup d’œil, pas de widget. Si votre application n’a rien qui mérite d’être montré sans l’ouvrir, un widget n’est qu’une décoration qui vous coûte de la maintenance et une cible d’extension supplémentaire.
  • Les actions lourdes ou lentes n’ont pas leur place dans perform() ici. L’environnement d’exécution des widgets et des commandes est contraint. Si l’action exige du temps réel ou du calcul réel, le bouton devrait ouvrir l’application sur un état préparé, et non feindre de faire le travail dans l’extension.
  • Une activité en direct pour quelque chose qui n’est pas en direct. Les activités en direct sont faites pour des événements limités dans le temps et activement changeants. En utiliser une comme badge de statut permanent, c’est une mauvaise lecture de la surface et un moyen rapide de se retrouver sur la liste noire du système quant au budget d’activité.

Le savoir-faire ne consiste pas à apprendre trois API. Il consiste à concevoir des App Intents qui méritent d’être montés, puis à les monter là où l’utilisateur se trouve déjà : l’écran d’accueil qu’il consulte, le centre de contrôle vers lequel il balaie, la Dynamic Island qui lui montre déjà quelque chose. Construisez la capacité une seule fois, avec goût, et iOS vous offre les surfaces gratuitement.

FAQ

iOS 26 a-t-il introduit les widgets interactifs ?

Non. Les widgets interactifs sont arrivés avec iOS 17 et les commandes du centre de contrôle avec iOS 18 ; iOS 26 leur a fait adopter le matériau Liquid Glass et le rendu accentué afin qu’ils s’accordent au langage de conception du système4. Traitez avec méfiance les affirmations selon lesquelles iOS 26 aurait « introduit » les widgets interactifs : le changement apporté par iOS 26 est un rafraîchissement visuel, pas une réécriture.

Comment un bouton à l’intérieur d’un widget iOS fait-il réellement son travail ?

Le bouton exécute un App Intent. Un Button ou un Toggle dans un widget invoque un AppIntent nommé et typé doté d’une méthode perform(), de sorte que le widget agit sans ouvrir l’application. Le même intent alimente une commande du centre de contrôle, un bouton d’activité en direct, une phrase Siri et une action Shortcuts5.

Qu’est-ce qui a réellement changé pour les widgets dans iOS 26 ?

La présentation, pas l’architecture. Les widgets adoptent Liquid Glass et gagnent des modes de rendu accentués afin de se teinter correctement sur l’écran d’accueil, l’écran verrouillé et en mode StandBy4. L’interactivité fonctionne exactement comme sur iOS 18, de sorte qu’un widget interactif existant a besoin d’une passe de conception, pas d’une réécriture.

Comment les activités en direct se mettent-elles à jour quand l’application n’est pas en cours d’exécution ?

Par notification push. Vous vous inscrivez à pushTokenUpdates, vous envoyez des charges utiles push ActivityKit depuis votre backend, et le système met à jour l’écran verrouillé et la Dynamic Island sans que votre application s’exécute3. La justesse de l’activité dépend alors d’un contrat serveur, de la fiabilité des notifications push et d’une politique de date de péremption, et non du seul code local.

Où un seul App Intent peut-il apparaître ?

Le même type AppIntent se monte dans un Button/Toggle de widget, un ControlWidget du centre de contrôle / de l’écran verrouillé / du bouton Action, une activité en direct et sa Dynamic Island, une phrase Siri, une action Shortcuts, et comme une action qu’Apple Intelligence peut invoquer5. Concevez la capacité une seule fois et les surfaces ne sont que des enveloppes.

Quand ne devrais-je pas construire un widget ou une activité en direct ?

Renoncez à un widget quand l’application n’a aucun état consultable d’un coup d’œil qui mérite d’être montré sans l’ouvrir. Gardez les actions lourdes ou lentes hors de perform() dans l’environnement contraint du widget ; ouvrez plutôt l’application sur un état préparé. Et n’utilisez pas une activité en direct comme badge de statut permanent ; elles sont faites pour des événements limités dans le temps et activement changeants, et en détourner une grignote votre budget d’activité.



  1. Apple Developer, « Adding interactivity to widgets and Live Activities ». Les widgets interactifs (iOS 17 et ultérieur) utilisent les Button(intent:) et Toggle(isOn:intent:) SwiftUI adossés à un AppIntent (ou un SetValueIntent pour les interrupteurs) ; le perform() de l’intent s’exécute dans l’extension de widget sans lancer l’application, et la chronologie se recharge pour refléter le résultat. 

  2. Apple Developer, « Creating controls to perform actions across the system » et le protocole ControlWidget. Les commandes (iOS 18 et ultérieur) sont construites à partir de ControlWidgetButton et ControlWidgetToggle câblés à des App Intents, et apparaissent dans le centre de contrôle, sur l’écran verrouillé et sur le bouton Action. 

  3. Apple Developer, « ActivityKit » et « Displaying live data with Live Activities ». ActivityAttributes et ActivityConfiguration définissent et rendent l’écran verrouillé et la Dynamic Island ; ActivityKit démarre, met à jour et termine les activités, et les mises à jour pilotées par serveur utilisent les notifications push avec pushTokenUpdates

  4. Rendu des widgets d’iOS 26 : les widgets adoptent le matériau Liquid Glass et le mode de rendu accentué, contrôlés via WidgetRenderingMode et la valeur d’environnement \.widgetRenderingMode. Le modèle d’interactivité (les App Intents dans les widgets et les commandes) est inchangé depuis iOS 17 (widgets) et iOS 18 (commandes). Apple, « WWDC 2025: the new software design » et la documentation WidgetKit

  5. Apple Developer, « App Intents ». Le même type AppIntent est l’unité que le système expose à travers Siri, Shortcuts, Spotlight, les surfaces des widgets et des commandes, et Apple Intelligence. Analyse de l’auteur sur le modèle multi-surfaces : App Intents Are Apple’s New API to Your App, App Intents 2 and the iOS 26 additions et the three surfaces of an iOS app

Articles connexes

Les Live Activities sont une machine à états, pas un badge

La Live Activity de Return ressemble à un compte à rebours sur l'écran verrouillé. C'est en réalité une machine à cinq é…

17 min de lecture

Le framework Translation d'Apple : gratuit, sur l'appareil et plus pointu qu'il n'y paraît

Le framework Translation d'Apple : traduction gratuite et sur l'appareil via translationPresentation et TranslationSessi…

10 min de lecture

The Robots Are Taking Exams in My Search Console

First-party GSC data: 91% of 3.8M impressions fail a human-query filter. Exam questions, pasted errors, and agent sweeps…

10 min de lecture