@AppStorage in SwiftUI — wat is het, UserDefaults en het opslaan van instellingen

Auteur: IT Sectr Gepubliceerd: 2026-06-25 Leestijd: 7 min

@AppStorage in SwiftUI — property wrapper voor het werken met UserDefaults, die automatisch de waarde synchroniseert met de UI. Bij wijziging van een eigenschap gedeclareerd via @AppStorage, wordt de nieuwe waarde onmiddellijk opgeslagen in UserDefaults, en wanneer UserDefaults extern wordt gewijzigd — door een widget of extensie — wordt de View automatisch opnieuw getekend. Volgens Apple Developer Documentation (2025), ondersteunt @AppStorage String, Int, Double, Bool, Data, URL en hun optionele versies, wat zorgt voor reactieve opslag van gebruikersinstellingen zonder handmatige observatiecode.

Belangrijkste punten

  • @AppStorage — property wrapper voor reactief werken met UserDefaults in SwiftUI
  • Automatisch opslaan — waarde wordt bij elke wijziging in UserDefaults geschreven
  • Automatische UI-update — View wordt opnieuw getekend bij wijziging van UserDefaults vanuit elke bron
  • Ondersteunde typen: String, Int, Double, Bool, Data, URL en optionele versies
  • Standaardwaarde wordt ingesteld in de declaratie en gebruikt bij de eerste start

Wat is @AppStorage in SwiftUI?

@AppStorage is een property wrapper geïntroduceerd door Apple in iOS 14, die een eigenschap van een View koppelt aan een sleutel in UserDefaults. Bij het lezen van de eigenschap laadt SwiftUI de waarde uit UserDefaults op basis van de opgegeven sleutel. Bij het schrijven — slaat het de nieuwe waarde op en stelt het de View op de hoogte van de noodzaak tot opnieuw tekenen.

Vóór de komst van @AppStorage moesten ontwikkelaars handmatig UserDefaults lezen in onAppear, zich abonneren op de UserDefaults.didChangeNotification-melding en @State bijwerken bij wijzigingen. @AppStorage automatiseert de hele cyclus: een declaratie op één regel vervangt 15–20 regels boilerplate-code. Bovendien zorgt @AppStorage voor bidirectionele synchronisatie — als de UserDefaults-waarde wordt gewijzigd vanuit een ander proces (bijv. App Extension of Widget), ontvangt de View nog steeds de update.

Architectonisch is @AppStorage geïmplementeerd als DynamicProperty, waardoor SwiftUI afhankelijkheden kan volgen en de View opnieuw kan tekenen bij wijziging van de geobserveerde waarde. Dit maakt het ideaal voor het opslaan van gebruikersinstellingen: interfacetaal, in-/uitschakelen van functies, laatst geselecteerd tabblad, gebruikersnaam.

@AppStorage vs UserDefaults: vergelijking

Hoewel @AppStorage onder de motorkap UserDefaults gebruikt, verschillen de benaderingen van opslag fundamenteel. UserDefaults is een laag-niveau API die handmatig beheer van lezen, schrijven en wijzigingsmeldingen vereist. @AppStorage is een SwiftUI-abstractie die uit de doos reactief gedrag biedt.

UserDefaults is geschikt voor eenmalige bewerkingen: laden van instellingen bij het starten van de app, schrijven van analyses, cachen van tokens. @AppStorage — voor instellingen die reactief de UI moeten bijwerken: themaschakelaars, taalkeuze, opslaan van interface-staat. Direct gebruik van UserDefaults binnen een View is een antipatroon, omdat de View niet op de hoogte raakt van wijzigingen zonder extra abonnement.

Parameter@AppStorageUserDefaults
ReactiviteitAutomatischVereist abonnement op meldingen
Boilerplate1 regel per eigenschap15–20 regels per eigenschap
TypenString, Int, Double, Bool, Data, URLAlle typen + gearchiveerde objecten
Aangepaste typenVia RawRepresentableVia NSKeyedArchiver
App ExtensionAutomatische synchronisatieHandmatig abonnement

Voor eenvoudige instellingen met reactieve UI is @AppStorage de voorkeurskeuze. Voor complexe gegevens (arrays, woordenboeken, aangepaste objecten) gebruikt u een combinatie van UserDefaults met @State en handmatige abonnementen op wijzigingen, of stapt u over op SwiftData / Core Data voor gestructureerde opslag.

Ondersteunde gegevenstypen

@AppStorage ondersteunt de standaardtypen die UserDefaults direct kan serialiseren: String, Int, Double, Bool, Data, URL. Voor elk type is er een optionele versie (String?, Int?, Double?, Bool?, Data?, URL?), waarmee onderscheid kan worden gemaakt tussen „niet ingesteld” en „lege waarde”.

Voor het opslaan van aangepaste typen die voldoen aan het RawRepresentable-protocol, werkt @AppStorage ook automatisch. Als een enum een rawValue van het type String of Int heeft, kan het direct worden gebruikt: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI serialiseert/deserialiseert automatisch de waarde 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("Gestart \(launchCount) keer")
        }
    }
}

In het voorbeeld worden verschillende @AppStorage-typen gebruikt: String met de standaardwaarde „Guest”, Int voor de startteller, Bool voor het donkere thema, enum AppTheme met rawValue van het type String en optionele Date? voor de laatste openingstijd. Elke eigenschap is gekoppeld aan een UserDefaults-sleutel die als eerste argument is opgegeven. De standaardwaarde wordt gebruikt als de sleutel bij de eerste start niet in de opslag aanwezig is.

Observeren van Store-wijzigingen

Een van de belangrijkste voordelen van @AppStorage — het automatisch observeren van UserDefaults-wijzigingen vanuit elke bron. Als een App Extension of Widget een waarde wijzigt, ontvangt @AppStorage in de bovenliggende applicatie een melding en tekent de View opnieuw. Dit wordt bereikt via het KVO-mechanisme (Key-Value Observing), dat @AppStorage automatisch instelt op UserDefaults.didChangeNotification.

In de praktijk betekent dit dat als een gebruiker een instelling wijzigt in een Widget (bijv. het donkere thema inschakelt), de applicatie deze wijziging onmiddellijk overneemt. Zo werkt ook de synchronisatie tussen de hoofdapplicatie en Share Extension, Watch App of Today Widget. De ontwikkelaar hoeft geen code te schrijven voor interprocesgegevensuitwisseling — @AppStorage doet dit automatisch.

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("Donkere modus gewijzigd naar \(newValue)")
                }
        }
    }
}

Toggle is via @AppStorage gekoppeld aan $isDarkMode. Bij het omschakelen wordt de waarde automatisch opgeslagen in UserDefaults onder de sleutel „isDarkMode”. De modifier .onChange maakt het mogelijk om een nevenactie uit te voeren bij wijziging — bijvoorbeeld het verzenden van analytics of het bijwerken van de UI van andere schermen. Als Widget dezelfde sleutel wijzigt, roept @AppStorage ook onChange aan, wat de consistentie van de status waarborgt.

@AppStorage codevoorbeelden

Laten we een volledig instellingenscherm van een applicatie bekijken dat @AppStorage gebruikt voor het opslaan van alle configuraties. Het formulier bevat secties met verschillende soorten instellingen: tekstvelden, schakelaars, tellers — alle waarden worden automatisch opgeslagen in 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("Profiel")) {
                    TextField("Display name", text: $displayName)
                }

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

                Section {
                    Button("Instellingen resetten") {
                        UserDefaults.standard.removePersistentDomain(
                            forName: Bundle.main.bundleIdentifier!)
                    }
                    .tint(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }
}

Het formulier bevat vier @AppStorage-eigenschappen van verschillende typen: String voor de naam, Bool voor meldingen, Int voor het aantal resultaten en String voor het geselecteerde tabblad. Alle besturingselementen zijn via Binding aan de eigenschappen gekoppeld ($displayName, $notificationsEnabled enz.). De knop „Reset settings” reset alle UserDefaults door het domein van de applicatie te verwijderen — daarna keert @AppStorage automatisch terug naar de standaardwaarden.

Synchronisatie van @AppStorage met 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 = "systeem"

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

    var body: some View {
        Form {
            Picker("Widget theme", selection: $widgetTheme) {
                Text("Systeem").tag("system")
                Text("Licht").tag("licht")
                Text("Donker").tag("donker")
            }
            Picker("Accent color", selection: $widgetColor) {
                Text("Blauw").tag("blue")
                Text("Groen").tag("groen")
                Text("Rood").tag("rood")
            }
        }
    }
}

Voor App Group (gedeelde opslag tussen de applicatie en extensies) accepteert @AppStorage de parameter store: UserDefaults(suiteName:). Waarden worden opgeslagen in een gedeelde container die toegankelijk is voor de hoofdapplicatie, Widget, Watch App en andere extensies van dezelfde groep. Widget kan deze instellingen lezen en bij wijziging in de applicatie wordt Widget automatisch bijgewerkt via het UserDefaults-observeringsmechanisme.

Veelgestelde vragen

Wat is het verschil tussen @AppStorage en @State?

@State slaat de waarde alleen in het geheugen op en wordt gereset bij het opnieuw starten van de applicatie. @AppStorage slaat de waarde op in UserDefaults en herstelt deze bij de volgende start. Gebruik @State voor tijdelijke schermgegevens, @AppStorage voor instellingen die een herstart moeten overleven.

Kan @AppStorage met Enum worden gebruikt?

Ja, als Enum het RawRepresentable-protocol implementeert met rawValue van het type String of Int. Voorbeeld: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI serialiseert automatisch de enum via rawValue en herstelt deze bij het laden.

Hoe wis ik alle @AppStorage-waarden?

Roep UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) aan voor de standaardopslag of removeObject(forKey:) voor een specifieke sleutel. Na het wissen keren alle @AppStorage-eigenschappen terug naar de standaardwaarden zoals gespecificeerd in de declaratie.

Werkt @AppStorage met App Extensions?

Ja, gebruik voor synchronisatie tussen de applicatie en extensies App Group: @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!). Widget, Share Extension en Watch App kunnen lezen en schrijven in dezelfde UserDefaults, en wijzigingen worden automatisch gevolgd.

Hoeveel gegevens kunnen worden opgeslagen in @AppStorage?

@AppStorage gebruikt UserDefaults, dat is bedoeld voor kleine hoeveelheden gegevens: instellingen, tokens, tellers. De aanbevolen limiet is tot 100 KB per applicatie. Voor gestructureerde of grote gegevens (objectarrays, mediabestanden) gebruikt u SwiftData, Core Data of het bestandssysteem.

Samenvatting

  • @AppStorage — property wrapper voor reactieve opslag van instellingen in UserDefaults
  • Automatisch opslaan en automatische UI-update bij wijziging van de waarde vanuit elke bron
  • Ondersteunt String, Int, Double, Bool, Data, URL en RawRepresentable enums
  • Standaardwaarde wordt ingesteld in de declaratie en hersteld bij de eerste start
  • App Group maakt synchronisatie van @AppStorage tussen applicatie en extensies mogelijk
  • UserDefaults is alleen geschikt voor kleine hoeveelheden gegevens — tot 100 KB
  • Gebruik @AppStorage voor gebruikersinstellingen, @State voor tijdelijke schermstatussen

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook