@ObservedObject: wat is het, observeren van objecten en View-updates

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

@ObservedObject is een property wrapper in SwiftUI waarmee een View wijzigingen kan observeren in een ObservableObject dat elders in de hiërarchie is gemaakt. In tegenstelling tot @StateObject maakt @ObservedObject geen object aan — het abonneert zich alleen op de publisher objectWillChange en hertekent de View bij het bijwerken van @Published-eigenschappen. Dit maakt @ObservedObject de juiste keuze voor onderliggende Views die gegevens van de ouder via de initializer ontvangen. Volgens het artikel van Paul Hudson — Hacking with Swift (2025) wordt een typische SwiftUI-app-architectuur als volgt opgebouwd: de root-View gebruikt @StateObject om een viewmodel te maken en alle onderliggende Views ontvangen het via @ObservedObject, wat een enkele bron van waarheid biedt zonder gegevensduplicatie.

Belangrijkste punten

  • @ObservedObject — property wrapper voor het observeren van een ObservableObject gemaakt in de bovenliggende View.
  • Bezit het object niet — in tegenstelling tot @StateObject beheert @ObservedObject de levenscyclus van het object niet.
  • Abonnement op wijzigingen — bij wijziging van @Published-eigenschappen wordt de View automatisch hertekend.
  • Doorgegeven via initializer — het object wordt doorgegeven aan de onderliggende View via de initializer-parameter.
  • iOS 13+ — @ObservedObject is beschikbaar vanaf de eerste versie van SwiftUI, in tegenstelling tot @StateObject (iOS 14+).

Wat is @ObservedObject in SwiftUI

@ObservedObject is een property wrapper die een View abonneert op ObservableObject-wijzigingen. Wanneer een object gemarkeerd met @ObservedObject een van zijn met @Published gedeclareerde eigenschappen wijzigt, hertekent SwiftUI de View automatisch. @ObservedObject maakt geen object aan — het legt alleen een verbinding tussen een bestaande ObservableObject-instantie en de View die op de wijzigingen moet reageren.

Het belangrijkste verschil tussen @ObservedObject en @StateObject — is eigendom. @ObservedObject gaat ervan uit dat het object ergens hoger in de View-hiërarchie is gemaakt en opgeslagen. De onderliggende View ontvangt een verwijzing naar dit object via de initializer en observeert het eenvoudigweg. Als de onderliggende View opnieuw wordt gemaakt, ontvangt het dezelfde verwijzing van de ouder — gegevens gaan niet verloren.

Volgens Apple Developer Documentation — SwiftUI (2025) is @ObservedObject beschikbaar vanaf iOS 13, wat het de enige optie maakt voor het observeren van ObservableObject in projecten die oudere iOS-versies ondersteunen. In iOS 14+ heeft @StateObject de voorkeur voor het maken van objecten, maar @ObservedObject blijft relevant voor het doorgeven van bestaande objecten.

Hoe werkt @ObservedObject

Het mechanisme van @ObservedObject is gebaseerd op het ObservableObject-protocol uit het Combine-framework. Elke klasse die voldoet aan ObservableObject krijgt automatisch een publisher objectWillChange die een signaal stuurt voordat een @Published-eigenschap wijzigt. SwiftUI abonneert zich via @ObservedObject op deze publisher en markeert bij ontvangst van het signaal de View als hertekening vereisend.

swift
class TaskViewModel: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var isLoading = false
    
    func loadTasks() async {
        isLoading = true
        // gegevens ophalen
        isLoading = false
    }
}

struct TaskListView: View {
    @ObservedObject var viewModel: TaskViewModel
    
    var body: some View {
        List(viewModel.tasks) { task in
            Text(task.title)
        }
        .task { await viewModel.loadTasks() }
    }
}

Wanneer de bovenliggende View viewModel doorgeeft aan TaskListView via de initializer, maakt SwiftUI een verbinding tussen het object en de View. Bij wijziging van de tasks-array of de isLoading-vlag hertekent SwiftUI TaskListView. Het object blijft daarbij onveranderd — het wordt in de bovenliggende View opgeslagen via @StateObject.

@ObservedObject vs @StateObject: wanneer wat te gebruiken

Het verschil tussen @ObservedObject en @StateObject — is het verschil tussen waarnemer en eigenaar. @StateObject maakt een object aan en beheert de levenscyclus ervan. @ObservedObject observeert alleen een object dat elders is gemaakt en opgeslagen. De keuze tussen hen wordt bepaald door de verantwoordelijkheid van de View voor de gegevens.

ScenarioAanbevelingReden
View maakt gegevens aan@StateObjectView bezit het object en is verantwoordelijk voor de levenscyclus
View ontvangt gegevens@ObservedObjectView observeert alleen, het object leeft in de ouder
Ondersteuning iOS 13@ObservedObject@StateObject niet beschikbaar, gebruik @ObservedObject met handmatig beheer
Herbruikbare component@ObservedObjectComponent moet geen gegevens maken — het ontvangt ze van buitenaf

Hoofdregel: als de View een object maakt — @StateObject. Als de View een object ontvangt — @ObservedObject. Overtreding van deze regel in de richting van @ObservedObject voor het maken van een object leidt tot gegevensverlies bij herbouw van de View. Overtreding in de richting van @StateObject voor het ontvangen van een object creëert een gedupliceerde instantie, onafhankelijk van de ouder.

Voorbeelden van @ObservedObject-gebruik

Een typisch gebruiksscenario voor @ObservedObject — een takenlijst, waarbij de root-View een viewmodel maakt en de lijstcel het ontvangt via @ObservedObject. Elke cel kan methoden van het viewmodel aanroepen en wijzigingen worden automatisch in de hele lijst weergegeven, omdat alle cellen hetzelfde object observeren.

swift
struct TaskRow: View {
    @ObservedObject var viewModel: TaskViewModel
    let task: Task
    
    var body: some View {
        HStack {
            Text(task.title)
            Spacer()
            Button("Gereed") {
                viewModel.completeTask(task)
            }
        }
    }
}

struct TaskListContainer: View {
    @StateObject var viewModel = TaskViewModel()
    
    var body: some View {
        List(viewModel.tasks) { task in
            TaskRow(viewModel: viewModel, task: task)
        }
    }
}

In dit voorbeeld maakt TaskListContainer viewModel aan via @StateObject en elke TaskRow ontvangt het via @ObservedObject. Wanneer de gebruiker „Done” in een rij klikt, wijzigt viewModel.completeTask de published-eigenschap en alle Views die dit object observeren, worden automatisch bijgewerkt.

Veelvoorkomende fouten met @ObservedObject

De meest voorkomende fout — het gebruik van @ObservedObject om een object binnen een View te maken. Wanneer de View wordt herbouwd (bijv. bij wijziging van de state), maakt SwiftUI een nieuwe ObservableObject-instantie aan, wat leidt tot verlies van alle verzamelde gegevens. Deze fout is bijzonder pijnlijk in NavigationStack, waar een gebruiker een formulier kan invullen en bij terugkeer gegevens kan verliezen.

Fout: @ObservedObject in plaats van @StateObject

swift
// ❌ Gegevensverlies: @ObservedObject behoudt object niet
struct FormView: View {
    @ObservedObject var formVM = FormViewModel()
    // Nieuwe formVM gemaakt bij elke herbouw van View!
}

// ✅ Correct: @StateObject behoudt het object
struct FormView: View {
    @StateObject var formVM = FormViewModel()
    // Object eenmaal gemaakt voor de levensduur van de View
}

Fout: @StateObject doorgeven waar @ObservedObject nodig is

Als een onderliggende View dezelfde ObservableObject via @StateObject declareert, maakt het een onafhankelijke kopie. Wijzigingen in het bovenliggende object zijn niet zichtbaar in de onderliggende en vice versa. Gebruik altijd @ObservedObject voor onderliggende Views die het object van buitenaf ontvangen.

Alternatieven voor @ObservedObject in SwiftUI

In modern SwiftUI zijn er verschillende alternatieven voor @ObservedObject, elk met zijn eigen voordelen. De keuze hangt af van de applicatiearchitectuur, iOS-versie en het specifieke gebruiksscenario.

  • @EnvironmentObject — maakt het mogelijk om een object uit de SwiftUI-omgeving te halen zonder expliciete overdracht via de initializer. Handig voor objecten die op veel schermen nodig zijn, maar vereist expliciete injectie via .environmentObject().
  • @State + @Binding — voor eenvoudige waardetypen zijn geen ObservableObject nodig. Gebruik @State voor opslag en @Binding voor overdracht naar onderliggende Views.
  • @AppStorage — voor UserDefaults-waarden die automatisch met de View moeten worden gesynchroniseerd.
  • @SceneStorage — voor het opslaan van tijdelijke toestand tussen herstarts van de scène (bijv. positie in een lijst).

De keuze tussen @ObservedObject en @EnvironmentObject — is een kwestie van stijl en architectuur. @ObservedObject toont expliciet de afhankelijkheden van de View via de initializer, wat de code voorspelbaarder maakt. @EnvironmentObject is handig voor diepe hiërarchieën, maar verbergt afhankelijkheden, wat debuggen kan bemoeilijken.

Veelgestelde vragen

Kan @ObservedObject worden gebruikt zonder @StateObject in de ouder?

Ja, als het object buiten SwiftUI wordt gemaakt en opgeslagen — bijvoorbeeld in AppDelegate of singleton. In dit geval abonneert @ObservedObject zich eenvoudig op wijzigingen van het bestaande object. Voor objecten die binnen de SwiftUI-hiërarchie worden gemaakt, is echter altijd een @StateObject ergens hoger nodig.

Waarom werkt @ObservedObject soms de View niet bij?

De meest waarschijnlijke oorzaak — de eigenschap wordt niet via @Published gewijzigd of niet het object zelf, maar de interne structuur ervan wordt gewijzigd zonder objectWillChange aan te roepen. Gebruik voor verzamelingen toewijzing van een nieuwe kopie: array.append() is niet voldoende — de hele array moet opnieuw worden toegewezen via array = array + [element].

Beïnvloedt @ObservedObject de prestaties?

@ObservedObject zelf veroorzaakt geen significante belasting. Problemen ontstaan bij frequente wijzigingen van @Published-eigenschappen — elke wijziging triggert het hertekenen van alle observerende Views. Gebruik voor optimalisatie EquatableView, verminder het aantal published-eigenschappen en vermijd onnodige updates.

Wat is het verschil tussen @ObservedObject en @Binding?

@ObservedObject observeert de hele ObservableObject-klasse en hertekent de View bij elke wijziging van de published-eigenschappen. @Binding maakt een tweerichtingsverbinding met een specifieke waarde (String, Int, Bool) en maakt lezen en schrijven mogelijk. @Binding is lichter en vereist geen ObservableObject.

Kunnen @ObservedObject en @Published in dezelfde klasse worden gecombineerd?

Ja, dit is een standaardpatroon. @Published binnen ObservableObject integreert automatisch met @ObservedObject. Elke @Published-eigenschap voegt een waarnemer toe aan de objectWillChange-publisher. Bij wijziging van een van hen worden alle Views met @ObservedObject voor dit object hertekend.

Samenvatting

  • @ObservedObject — property wrapper voor het observeren van ObservableObject gemaakt elders in de hiërarchie.
  • Bezit het object niet — in tegenstelling tot @StateObject beheert @ObservedObject de levenscyclus niet en maakt geen object.
  • Abonnement via Combine — SwiftUI abonneert zich automatisch op de objectWillChange-publisher van ObservableObject.
  • iOS 13+ — @ObservedObject is beschikbaar vanaf de eerste versie van SwiftUI, belangrijk voor projecten met oude ondersteuning.
  • Doorgeven via initializer — het object wordt expliciet doorgegeven aan de onderliggende View, wat afhankelijkheden transparant maakt.
  • Eigendomsfout — het gebruik van @ObservedObject om een object te maken leidt tot gegevensverlies bij herbouw van de View.
  • Alternatieven — @EnvironmentObject voor injectie via omgeving, @State/@Binding voor waardetypen.

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