@StateObject: wat het is, aanmaken en beheren van ObservableObject

Auteur: IT Sectr Gepubliceerd: 2026-06-26 Leestijd: 9 min

@StateObject is een property wrapper in SwiftUI die een ObservableObject-instantie aanmaakt en bezit gedurende de volledige levenscyclus van een View. Wanneer een View voor het eerst op het scherm verschijnt, initialiseert @StateObject het object en bewaart het totdat de View uit het geheugen wordt verwijderd. Dit garandeert dat gegevens niet worden gereset bij herbouw van de interface — bijvoorbeeld bij themawissel of bijwerken van de bovenliggende View. Volgens Apple Developer Documentation (2025) moet @StateObject worden gebruikt als de belangrijkste bron van waarheid (source of truth) voor ObservableObject in de SwiftUI-hiërarchie, terwijl onderliggende Views het reeds aangemaakte object ontvangen via @ObservedObject of @EnvironmentObject.

Belangrijkste punten

  • @StateObject — property wrapper voor het aanmaken en bezitten van ObservableObject binnen een View.
  • Eenmalige aanmaak — het object wordt eenmalig geïnitialiseerd gedurende de levensduur van de View en wordt niet opnieuw aangemaakt bij herbouwingen.
  • Source of truth — @StateObject is de bron van waarheid in de hiërarchie, in tegenstelling tot @ObservedObject.
  • Levenscyclus — het object leeft zolang de View in het geheugen bestaat en wordt samen ermee vernietigd.
  • Initialisatie — @StateObject vereist een beginwaarde bij aanmaak, meestal via init met parameters.

Wat is @StateObject in SwiftUI

@StateObject is een property wrapper geïntroduceerd in iOS 14 die een View in staat stelt een instantie van een klasse die voldoet aan het ObservableObject-protocol aan te maken en te bezitten. In tegenstelling tot @State, dat werkt met waardetypen (structuren), is @StateObject bedoeld voor referentietypen — klassen die SwiftUI op de hoogte kunnen stellen van wijzigingen in hun eigenschappen.

Wanneer een View @StateObject var viewModel: MyViewModel gebruikt, maakt SwiftUI automatisch een MyViewModel-instantie aan bij de eerste weergave van de View en slaat deze op in een speciale opslag van het framework. Bij elke update van de View (bijvoorbeeld bij wijziging van de bovenliggende toestand) maakt SwiftUI het object niet opnieuw aan — het gebruikt de bestaande instantie totdat de View uit de hiërarchie wordt verwijderd.

Volgens Apple WWDC Session 10137 (2024) lost @StateObject het probleem van gegevensverlies bij herbouw van de View op dat in iOS 13 bestond, toen ontwikkelaars ObservableObject in de bovenliggende View moesten aanmaken en via de initialisator moesten doorgeven. Dit leidde tot code-duplicatie en risico op onbedoelde herbouw van het object.

swift
import SwiftUI

class CounterViewModel: ObservableObject {
    @Published var count: Int = 0
    
    func increment() {
        count += 1
    }
}

struct CounterView: View {
    @StateObject var viewModel = CounterViewModel()
    
    var body: some View {
        VStack {
            Text("Aantal: \(viewModel.count)")
            Button("Verhogen", action: viewModel.increment)
        }
    }
}

Hoe werkt @StateObject

Het mechanisme van @StateObject is gebaseerd op de integratie van SwiftUI met het Combine-framework. Wanneer ObservableObject zijn eigenschappen markeert met het @Published-attribuut, abonneert SwiftUI zich automatisch op wijzigingen via de ingebouwde publisher in het ObservableObject-protocol. Bij wijziging van een gepubliceerde eigenschap stuurt het object een signaal via de objectWillChange-publisher, wat het hertekenen van alle Views die dit object observeren activeert.

SwiftUI slaat de ObservableObject-instantie op in een speciale opslag die aan een specifieke View-instantie is gekoppeld. Deze opslag wordt eenmalig aangemaakt bij de eerste render en blijft bestaan tot vernietiging van de View. Daarom garandeert @StateObject de stabiliteit van de verwijzing naar het object — SwiftUI beheert het geheugen automatisch, zonder afhankelijk te zijn van de View-initialisator.

Volgens objc.io — Thinking in SwiftUI (2025) gebruikt de interne implementatie van @StateObject een mechanisme dat vergelijkbaar is met @State, maar voor referentietypen: SwiftUI maakt een boxing-wrapper rond het object en beheert de levenscyclus via een eigen allocator, geoptimaliseerd voor frequente herbouwingen van de View-hiërarchie.

Levenscyclus van @StateObject

  • Aanmaak — bij de eerste verschijning van de View op het scherm roept SwiftUI de initialisator van het object aan en slaat de verwijzing op.
  • Herbouw — bij bijwerken van de bovenliggende View wordt het object niet opnieuw aangemaakt, de bestaande instantie wordt gebruikt.
  • Vernietiging — wanneer de View het scherm verlaat en uit de hiërarchie wordt verwijderd, roept SwiftUI de deinit van het object aan.

@StateObject vs @ObservedObject: belangrijkste verschillen

Het belangrijkste verschil tussen @StateObject en @ObservedObject is wie het object bezit. @StateObject maakt het object aan en slaat het op — het is de eigenaar. @ObservedObject observeert alleen een object dat elders is aangemaakt en via de initialisator of eigenschap is doorgegeven.

Kenmerk@StateObject@ObservedObject
EigendomMaakt aan en bezit het objectObserveert alleen
InitialisatieBinnen de View via init/defaultVan buitenaf, via parameter doorgegeven
LevenscyclusGebonden aan de levenscyclus van de ViewNiet gecontroleerd door de View
HerbouwWordt niet herbouwd bij updateKan van buitenaf worden vervangen
iOS-versieiOS 14+iOS 13+

De regel is eenvoudig: als een View ObservableObject aanmaakt — gebruik @StateObject. Als een View alleen een reeds bestaand object van de ouder ontvangt — gebruik @ObservedObject. Schending van deze regel leidt ofwel tot gegevensverlies (als je @ObservedObject gebruikt voor eigendom), ofwel tot overmatige objectaanmaak (als je @StateObject gebruikt voor observatie).

Wanneer @StateObject gebruiken

@StateObject moet worden gebruikt in Views die de bron van waarheid zijn voor een specifieke gegevensset. Typische scenario's zijn schermen met een eigen view model, root-schermen van navigatiestapels en modale presentaties die hun eigen toestand beheren.

  • Scherm met view model — elk scherm dat zijn eigen gegevens en logica beheert, moet zijn eigen view model aanmaken via @StateObject.
  • Root View — in een NavigationStack- of TabView-hiërarchie maakt het root-element gegevens aan en ontvangen onderliggende elementen deze via @ObservedObject.
  • Modale vensters — .sheet en .fullScreenCover vereisen vaak een eigen @StateObject voor het beheren van een formulier of proces.
  • Lijst met bewerking — elk rijtje van een lijst dat een bewerkingsformulier bevat, moet zijn eigen @StateObject hebben.
swift
struct ProfileView: View {
    @StateObject var viewModel = ProfileViewModel()
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("Name", text: $viewModel.name)
                TextField("Email", text: $viewModel.email)
                Button("Opslaan") {
                    viewModel.saveProfile()
                }
            }
            .navigationTitle("Profile")
        }
    }
}

Initialisatie van @StateObject met parameters

Initialisatie van @StateObject met parameters vereist speciale syntax, omdat SwiftUI het aanmaken van het object onafhankelijk beheert. Je kunt niet eenvoudigweg parameters doorgeven aan de initialisator — je moet een escaping closure of een aparte aanmaakmethode gebruiken.

Volgens Swift by Sundell (2024) is de schoonste methode het gebruik van een fabrieksmethode of closure die SwiftUI zal aanroepen bij de eerste aanmaak van het object. Een alternatieve benadering — ObservableObject initialiseren in de bovenliggende View en doorgeven via @StateObject met de standaard initialisator.

swift
class UserViewModel: ObservableObject {
    @Published var user: User
    
    init(user: User) {
        self.user = user
    }
}

struct UserDetailView: View {
    @StateObject var viewModel: UserViewModel
    
    init(user: User) {
        _viewModel = StateObject(wrappedValue: UserViewModel(user: user))
    }
    
    var body: some View {
        Text(viewModel.user.name)
    }
}

Het is belangrijk om te onthouden dat de View-initialisator met @StateObject een underscore voor de eigenschapsnaam (_viewModel) moet gebruiken om toegang te krijgen tot de property wrapper zelf, niet tot de waarde ervan. Dit is een standaard Swift-patroon voor het werken met property wrappers in initialisatoren.

Veelvoorkomende fouten met @StateObject

De meest voorkomende fout is het gebruik van @ObservedObject in plaats van @StateObject voor een View dat het object zou moeten bezitten. In dit geval wordt het object bij elke herbouw van de ouder opnieuw aangemaakt, wat leidt tot verlies van alle verzamelde gegevens. Deze fout is bijzonder verraderlijk in complexe hiërarchieën met NavigationStack of TabView.

  • Gegevensverlies bij navigatie — als een onderliggend scherm @ObservedObject gebruikt voor zijn eigen view model, worden bij terugkeer en heropenen de gegevens gereset.
  • Geheugenlek — het aanmaken van @StateObject in een bovenliggende View die nooit wordt verwijderd, kan leiden tot ophoping van objecten als elk onderliggend scherm ook ongecontroleerd @StateObject aanmaakt.
  • Objectduplicatie — het doorgeven van één ObservableObject aan meerdere @StateObject in verschillende Views creëert meerdere onafhankelijke instanties die niet met elkaar synchroniseren.

Om deze problemen te voorkomen, volg je de eenvoudige regel: één @StateObject per bron van waarheid. Als gegevens moeten worden gedeeld tussen meerdere schermen — maak dan @StateObject eenmalig aan in de root View en geef het door via @ObservedObject of @EnvironmentObject aan onderliggende elementen.

swift
// ❌ Fout: @ObservedObject voor het bezitten van een object
struct BadView: View {
    @ObservedObject var vm = ViewModel() // wordt bij elke update opnieuw aangemaakt!
}

// ✅ Juist: @StateObject voor het bezitten
struct GoodView: View {
    @StateObject var vm = ViewModel() // eenmalig aangemaakt voor de View-levensduur
}

Veelgestelde vragen

Wat is het verschil tussen @StateObject en @State?

@State werkt met waardetypen (structuren, strings, getallen) en slaat de waarde direct op in de SwiftUI-opslag. @StateObject werkt met referentietypen — klassen die voldoen aan ObservableObject. @State is geschikt voor eenvoudige lokale toestanden, @StateObject voor complexe objecten met logica en gepubliceerde eigenschappen.

Kan ik @StateObject gebruiken in iOS 13?

Nee, @StateObject is alleen beschikbaar vanaf iOS 14 en hoger. Gebruik voor iOS 13 @ObservedObject en maak ObservableObject aan in de bovenliggende View via @State met handmatig levenscyclusbeheer. Een alternatief is het gebruik van @State met struct in plaats van class voor gegevens die geen referentiesemantiek vereisen.

Wat gebeurt er als ik @StateObject gebruik in een onderliggende View waaraan het object van de ouder wordt doorgegeven?

De onderliggende View maakt zijn eigen kopie van ObservableObject aan, volledig onafhankelijk van de ouder. Wijzigingen in de ene hebben geen invloed op de andere. Dit is bijna altijd een fout: gebruik @ObservedObject voor het ontvangen van een object van de ouder en @StateObject alleen voor het aanmaken van een nieuw object binnen de View.

Wanneer wordt een via @StateObject aangemaakt object vernietigd?

Het object wordt vernietigd wanneer de View die het heeft aangemaakt volledig uit de SwiftUI-hiërarchie wordt verwijderd. Voor een scherm in NavigationStack gebeurt dit bij pop van de navigatiestapel. Voor een modaal venster — bij het sluiten ervan. Voor TabView — bij het wisselen van tabblad, als de View niet wordt gecachet.

Hoe geef ik parameters door aan @StateObject bij initialisatie?

Gebruik een aangepaste init met toegang tot de property wrapper via underscore: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Dit patroon maakt het mogelijk om willekeurige parameters aan ObservableObject door te geven, terwijl de garantie van eenmalige objectaanmaak gedurende de levensduur van de View behouden blijft.

Samenvatting

  • @StateObject — property wrapper voor het aanmaken en bezitten van ObservableObject binnen een View, beschikbaar vanaf iOS 14.
  • Garantie van eenmalige aanmaak — het object wordt eenmalig geïnitialiseerd en niet opnieuw aangemaakt bij herbouw van de View.
  • Source of truth — @StateObject is de bron van waarheid, @ObservedObject slechts de waarnemer.
  • Levenscyclus — het object leeft zolang de View in de SwiftUI-hiërarchie bestaat en wordt vernietigd bij het verlaten ervan.
  • Initialisatie met parameters — vereist toegang tot de property wrapper via _viewModel en StateObject(wrappedValue:).
  • Eigendomsfout — het gebruik van @ObservedObject voor het aanmaken van een object leidt tot gegevensverlies bij herbouw.
  • Eén object — één @StateObject — maak voor gedeelde gegevens @StateObject aan in de root View en geef het door aan onderliggende elementen via @ObservedObject.

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