@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 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.
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.
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.
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.
| Scenario | Aanbeveling | Reden |
|---|---|---|
| View maakt gegevens aan | @StateObject | View bezit het object en is verantwoordelijk voor de levenscyclus |
| View ontvangt gegevens | @ObservedObject | View observeert alleen, het object leeft in de ouder |
| Ondersteuning iOS 13 | @ObservedObject | @StateObject niet beschikbaar, gebruik @ObservedObject met handmatig beheer |
| Herbruikbare component | @ObservedObject | Component 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.
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.
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.
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.
// ❌ 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
}
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.
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.
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
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.
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].
@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.
@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.
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
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.
Lees ook