@AppStorage dans SwiftUI — qu'est-ce que c'est, UserDefaults et stockage des paramètres

Auteur : IT Sectr Publié le : 2026-06-25 Temps de lecture : 7 min

@AppStorage dans SwiftUI est un property wrapper pour travailler avec UserDefaults qui synchronise automatiquement la valeur avec l'interface utilisateur. Lorsqu'une propriété déclarée avec @AppStorage change, la nouvelle valeur est immédiatement enregistrée dans UserDefaults, et lorsque UserDefaults change de l'extérieur — par un widget ou une extension — la View est automatiquement redessinée. Selon Apple Developer Documentation (2025), @AppStorage prend en charge String, Int, Double, Bool, Data, URL et leurs versions optionnelles, offrant un stockage réactif des paramètres utilisateur sans code d'observation manuel.

Points Clés

  • @AppStorage — property wrapper pour un travail réactif avec UserDefaults dans SwiftUI
  • Auto-enregistrement — la valeur est écrite dans UserDefaults à chaque changement
  • Auto-mise à jour de l'UI — la View est redessinée lorsque UserDefaults change depuis n'importe quelle source
  • Types pris en charge : String, Int, Double, Bool, Data, URL et versions optionnelles
  • Valeur par défaut définie dans la déclaration et utilisée au premier lancement

Qu'est-ce que @AppStorage dans SwiftUI ?

@AppStorage est un property wrapper présenté par Apple dans iOS 14 qui lie une propriété de View à une clé dans UserDefaults. Lors de la lecture de la propriété, SwiftUI charge la valeur depuis UserDefaults via la clé spécifiée. Lors de l'écriture, il enregistre la nouvelle valeur et notifie la View qu'elle doit être redessinée.

Avant @AppStorage, les développeurs devaient lire manuellement UserDefaults dans onAppear, s'abonner à UserDefaults.didChangeNotification et mettre à jour @State lors des changements. @AppStorage automatise tout le cycle : une déclaration d'une ligne remplace 15 à 20 lignes de code répétitif. De plus, @AppStorage offre une synchronisation bidirectionnelle — si la valeur UserDefaults change depuis un autre processus (par exemple, App Extension ou Widget), la View reçoit quand même la mise à jour.

Architecturalement, @AppStorage est implémenté comme DynamicProperty, ce qui permet à SwiftUI de suivre les dépendances et de redessiner la View lorsque la valeur observée change. Cela le rend idéal pour stocker les paramètres utilisateur : langue de l'interface, activation/désactivation des fonctionnalités, dernier onglet sélectionné, nom d'utilisateur.

@AppStorage vs UserDefaults : Comparaison

Bien que @AppStorage utilise UserDefaults en interne, les approches de travail avec le stockage sont fondamentalement différentes. UserDefaults est une API de bas niveau qui nécessite une gestion manuelle de la lecture, de l'écriture et des notifications de changement. @AppStorage est une abstraction SwiftUI qui offre un comportement réactif prêt à l'emploi.

UserDefaults est adapté aux opérations ponctuelles : charger les paramètres au démarrage de l'application, écrire des analyses, mettre en cache des jetons. @AppStorage est destiné aux paramètres qui doivent mettre à jour l'UI de façon réactive : interrupteurs de thème, sélection de langue, sauvegarde de l'état de l'interface. Utiliser UserDefaults directement dans une View est un anti-modèle, car la View ne connaît pas les changements sans abonnement supplémentaire.

Paramètre@AppStorageUserDefaults
RéactivitéAutomatiqueNécessite un abonnement aux notifications
Boilerplate1 ligne par propriété15 à 20 lignes par propriété
TypesString, Int, Double, Bool, Data, URLTous les types + objets archivés
Types personnalisésVia RawRepresentableVia NSKeyedArchiver
App ExtensionSynchronisation automatiqueAbonnement manuel

Pour les paramètres simples avec UI réactive @AppStorage est le choix préféré. Pour les données complexes (tableaux, dictionnaires, objets personnalisés), utilisez une combinaison de UserDefaults avec @State et un abonnement manuel aux changements, ou passez à SwiftData / Core Data pour un stockage structuré.

Types de données pris en charge

@AppStorage prend en charge les types standards que UserDefaults peut sérialiser directement : String, Int, Double, Bool, Data, URL. Pour chaque type, il existe une version optionnelle (String?, Int?, Double?, Bool?, Data?, URL?) permettant de distinguer « non défini » et « valeur vide ».

Pour stocker des types personnalisés conformes au protocole RawRepresentable, @AppStorage fonctionne également automatiquement. Si une énumération a rawValue de type String ou Int, elle peut être utilisée directement : @AppStorage("theme") var theme: AppTheme = .system. SwiftUI sérialise/désérialise automatiquement la valeur via rawValue.

swift
enum AppTheme: String {
    case system, light, dark
}

struct SettingsView: View {
    @AppStorage("username") var username: String = "Guest"
    @AppStorage("launchCount") var launchCount: Int = 0
    @AppStorage("isDarkMode") var isDarkMode: Bool = false
    @AppStorage("appTheme") var theme: AppTheme = .system
    @AppStorage("lastOpened") var lastOpened: Date? = nil

    var body: some View {
        Form {
            TextField("Username", text: $username)
            Toggle("Dark mode", isOn: $isDarkMode)
            Text("Lancé \(launchCount) fois")
        }
    }
}

L'exemple utilise différents types @AppStorage : String avec valeur par défaut « Guest », Int pour un compteur de lancements, Bool pour le thème sombre, énumération AppTheme avec rawValue de type String, et un Date? optionnel pour la dernière ouverture. Chaque propriété est liée à une clé UserDefaults spécifiée comme premier argument. La valeur par défaut est utilisée si la clé est absente du stockage au premier lancement.

Observation des changements du Store

L'un des principaux avantages de @AppStorage est l'observation automatique des changements de UserDefaults depuis n'importe quelle source. Si une App Extension ou un Widget modifie une valeur, @AppStorage dans l'application parente reçoit la notification et redessine la View. Ceci est réalisé via le mécanisme KVO (Key-Value Observing) que @AppStorage configure automatiquement sur UserDefaults.didChangeNotification.

En pratique, cela signifie que si l'utilisateur modifie un paramètre dans un Widget (par exemple, active le thème sombre), l'application capte immédiatement le changement. La même synchronisation fonctionne entre l'application principale et Share Extension, Watch App ou Today Widget. Le développeur n'a pas besoin d'écrire de code pour l'échange de données entre processus — @AppStorage le fait automatiquement.

swift
struct ThemeSettingView: View {
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Toggle("Dark Mode", isOn: $isDarkMode)
                .onChange(of: isDarkMode) { oldValue, newValue in
                    print("Mode sombre changé en \(newValue)")
                }
        }
    }
}

Toggle est lié à $isDarkMode via @AppStorage. Lors du basculement, la valeur est automatiquement enregistrée dans UserDefaults sous la clé « isDarkMode ». Le modificateur .onChange permet d'exécuter un effet secondaire lors du changement — par exemple, envoyer des analyses ou mettre à jour l'UI d'autres écrans. Si un Widget modifie la même clé, @AppStorage déclenchera également onChange, assurant la cohérence de l'état.

Exemples de code @AppStorage

Examinons un écran de paramètres d'application complet qui utilise @AppStorage pour stocker toutes les configurations. Le formulaire contient des sections avec différents types de paramètres : champs de texte, interrupteurs, compteurs — toutes les valeurs sont automatiquement enregistrées dans UserDefaults.

swift
struct AppSettingsView: View {
    @AppStorage("displayName") var displayName = ""
    @AppStorage("notificationsEnabled") var notificationsEnabled = true
    @AppStorage("maxResults") var maxResults = 25
    @AppStorage("selectedTab") var selectedTab = "home"

    var body: some View {
        NavigationStack {
            Form {
                Section(header: Text("Profil")) {
                    TextField("Display name", text: $displayName)
                }

                Section(header: Text("Préférences")) {
                    Toggle("Enable notifications",
                           isOn: $notificationsEnabled)
                    Stepper("Max results: \(maxResults)",
                           value: $maxResults,
                           in: 10...100,
                           step: 5)
                }

                Section {
                    Button("Réinitialiser les paramètres") {
                        UserDefaults.standard.removePersistentDomain(
                            forName: Bundle.main.bundleIdentifier!)
                    }
                    .tint(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }
}

Le formulaire contient quatre propriétés @AppStorage de différents types : String pour le nom, Bool pour les notifications, Int pour le nombre de résultats et String pour l'onglet sélectionné. Tous les contrôles sont liés aux propriétés via Binding ($displayName, $notificationsEnabled, etc.). Le bouton « Reset settings » efface tous les UserDefaults en supprimant le domaine de l'application — après quoi @AppStorage revient automatiquement aux valeurs par défaut.

Synchronisation de @AppStorage avec App Group

swift
struct SharedSettingsView: View {
    let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")

    @AppStorage("widgetTheme", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetTheme: String = "système"

    @AppStorage("widgetColor", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetColor: String = "bleu"

    var body: some View {
        Form {
            Picker("Widget theme", selection: $widgetTheme) {
                Text("Système").tag("system")
                Text("Clair").tag("clair")
                Text("Sombre").tag("sombre")
            }
            Picker("Accent color", selection: $widgetColor) {
                Text("Bleu").tag("blue")
                Text("Vert").tag("vert")
                Text("Rouge").tag("rouge")
            }
        }
    }
}

Pour App Group (stockage partagé entre l'application et les extensions), @AppStorage accepte le paramètre store : UserDefaults(suiteName:). Les valeurs sont enregistrées dans le conteneur partagé accessible à l'application principale, Widget, Watch App et autres extensions du même groupe. Un Widget peut lire ces paramètres, et lorsqu'ils changent dans l'application, le Widget se met automatiquement à jour via le mécanisme d'observation UserDefaults.

Questions fréquentes

Quelle est la différence entre @AppStorage et @State ?

@State stocke la valeur uniquement en mémoire et se réinitialise au redémarrage de l'application. @AppStorage enregistre la valeur dans UserDefaults et la restaure au lancement suivant. Utilisez @State pour les données temporaires d'écran, @AppStorage pour les paramètres qui doivent survivre à un redémarrage.

Peut-on utiliser @AppStorage avec une Enum ?

Oui, si l'Enum implémente le protocole RawRepresentable avec rawValue de type String ou Int. Exemple : @AppStorage("theme") var theme: AppTheme = . system. SwiftUI sérialise automatiquement l'énumération via rawValue et la restaure au chargement.

Comment effacer toutes les valeurs @AppStorage ?

Appelez UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) pour le stockage standard ou removeObject(forKey:) pour une clé spécifique. Après effacement, toutes les propriétés @AppStorage reviendront aux valeurs par défaut spécifiées dans la déclaration.

@AppStorage fonctionne-t-il avec les App Extensions ?

Oui, pour la synchronisation entre l'application et les extensions, utilisez App Group : @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!). Widget, Share Extension et Watch App peuvent lire et écrire dans le même UserDefaults, et les changements sont automatiquement suivis.

Quelle quantité de données peut-on stocker dans @AppStorage ?

@AppStorage utilise UserDefaults, qui est conçu pour de petites quantités de données : paramètres, jetons, compteurs. La limite recommandée est de 100 Ko par application. Pour les données structurées ou volumineuses (tableaux d'objets, fichiers multimédia), utilisez SwiftData, Core Data ou le système de fichiers.

Résumé

  • @AppStorage — property wrapper pour le stockage réactif des paramètres dans UserDefaults
  • Auto-enregistrement et auto-mise à jour de l'UI lors du changement de valeur depuis n'importe quelle source
  • Prend en charge String, Int, Double, Bool, Data, URL et les enums RawRepresentable
  • Valeur par défaut définie dans la déclaration et restaurée au premier lancement
  • App Group permet de synchroniser @AppStorage entre l'application et les extensions
  • UserDefaults convient uniquement pour de petites quantités de données — jusqu'à 100 Ko
  • Utilisez @AppStorage pour les paramètres utilisateur, @State pour les états temporaires d'écran

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi