@ObservedObject är en Property Wrapper i SwiftUI för att observera en ObservableObject-instans som skickats utifrån. Till skillnad från @StateObject skapar @ObservedObject inte objektet — den prenumererar på ändringar av ett befintligt. Enligt Apple Developer Documentation (2025) används @ObservedObject i underordnade vyer som behöver spåra data som tillhör föräldern. @ObservedObject ger en reaktiv anslutning utan att hantera objektets livscykel.
Huvudpunkter
@ObservedObject är en Property Wrapper som prenumererar vyn på ändringar av ObservableObject. ObservableObject är ett protokoll från Combine-ramverket som kräver implementering av objectWillChange-publishern. När någon egenskap markerad med @Published ändras inuti ObservableObject skickar publishern en signal och SwiftUI ritar om alla vyer som prenumererar via @ObservedObject.
Huvudegenskapen hos @ObservedObject är avsaknad av ägande. Vyn är inte ansvarig för att skapa eller förstöra objektet. Objektet skapas i föräldravyn (via @StateObject) eller injiceras via @EnvironmentObject. Den underordnade vyn observerar bara ändringar och tar emot uppdateringar. Om objektet ersätts i föräldern växlar @ObservedObject till den nya instansen.
@ObservedObject är lämplig för scenarier med datadelning: användarmodell, gemensamma inställningar, anslutningsstatus till servern. När flera vyer på olika nivåer i hierarkin måste visa samma data skapar @ObservedObject i varje vy oberoende men samordnade prenumerationer på en källa.
Skillnaden mellan @ObservedObject och @StateObject är ett av de vanligaste ämnena på SwiftUI-intervjuer. Grundregeln: @StateObject skapar och äger objektet, @ObservedObject observerar ett befintligt. Brott mot denna regel leder till oväntad dataförlust eller dubbel initiering.
| Egenskap | @StateObject | @ObservedObject |
|---|---|---|
| Skapa objekt | Ja, vid initiering av vyn | Nej, tar emot färdigt |
| Ägande | Aktuell vy | Förälderkomponent |
| Unik instans | Ja, under hela livscykeln | Nej, kan ersättas |
| Återskapande vid rendering | Nej, behålls | Beror på föräldern |
| Var att använda | Rotvy-ägare | Underordnade vyer |
@StateObject garanterar att objektet skapas en gång och överlever upprepade initieringar av vystrukturen. @ObservedObject tar emot objektet utifrån och återskapas vid varje initiering av förälderstrukturen. Om föräldern använder @StateObject för objektet kan underordnade vyer säkert använda @ObservedObject — objektet kommer att vara unikt i hela hierarkin.
Spårningsmekanismen för @ObservedObject är baserad på Combine och ObservableObject-protokollet. Vid initiering anropar SwiftUI objectWillChange-publishern — objektet måste skicka en signal före ändring av @Published-egenskapen. Combine överför signalen till SwiftUI:s beroendegraf, som markerar alla beroende vyer som kräver uppdatering. Detta sker synkront före ändring av värdet.
class WeatherService: ObservableObject {
@Published var temperature: Double = 22.0
@Published var city: String = "Moscow"
}
struct WeatherView: View {
@ObservedObject var weather: WeatherService
var body: some View {
VStack {
Text("\\(weather.city)")
Text("\\(weather.temperature)°C")
}
}
}
I listningen är WeatherService ett ObservableObject med två @Published-egenskaper. WeatherView deklarerar @ObservedObject var weather: WeatherService och får instansen från föräldern. När temperature ändras aktiveras objectWillChange innan det nya värdet ställs in, SwiftUI ritar om WeatherView och den aktuella temperaturen visas. Prenumerationen hanteras automatiskt av SwiftUI — utvecklaren behöver inte anropa sink eller dispose.
Första mönstret — överföring av modell via initierare. Föräldern skapar ObservableObject via @StateObject och skickar det till underordnade vyer som @ObservedObject. Detta är en standard hierarkisk dataöverföring där rotvyn hanterar modellens livscykel och alla inkapslade komponenter prenumererar på ändringar.
Andra mönstret — EnvironmentObject, den globala versionen av @ObservedObject via SwiftUI Environment. Objektet injiceras på scennivå eller rotvynivå och är automatiskt tillgängligt för alla underordnade komponenter utan explicit överföring via initierare. Inuti den underordnade vyn fungerar @EnvironmentObject liknande @ObservedObject men hämtar objektet från miljön.
Tredje mönstret — komposition av flera ObservableObject. I komplexa applikationer kan en vy observera flera objekt: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. Detta separerar ansvaret mellan tjänster och bibehåller testbarheten för varje komponent.
struct DashboardView: View {
@ObservedObject var user: UserViewModel
@ObservedObject var network: NetworkMonitor
var body: some View {
VStack {
Text("Välkommen, \\(user.name)")
HStack {
Circle()
.fill(network.isConnected ? Color.green : Color.red)
.frame(width: 10, height: 10)
}
}
}
}
DashboardView observerar UserViewModel och NetworkMonitor. Varje objekt ansvarar för sin egen datadomän och meddelar självständigt vyn om ändringar. Om nätverket kopplas bort ändrar NetworkMonitor isConnected och SwiftUI ritar om DashboardView och uppdaterar indikatorns färg. Komposition av ObservableObject är det föredragna sättet att organisera data i SwiftUI-applikationer.
@Published är en Property Wrapper från Combine som automatiskt lägger till en utgivare till en egenskap inuti ObservableObject. När @Published-egenskapen ändras genererar Combine en händelse via objectWillChange-publishern. SwiftUI prenumererar på denna publisher när den använder @ObservedObject eller @StateObject och ritar om vyn vid varje nytt värde.
@Published stöder alla typer, inklusive optionella, samlingar och anpassade strukturer. För samlingar (arrayer, ordböcker) spårar SwiftUI dock bara referensersättning, inte innehållsändring. För att upptäcka tillägg eller borttagning av ett element måste du tilldela om hela samlingen eller använda ObservableObject med manuell objectWillChange.send().
En viktig detalj: @Published får endast finnas inuti en klass som implementerar ObservableObject. Användning av @Published utanför ObservableObject orsakar ett kompileringsfel. @Published kan inte heller tillämpas på egenskaper med lat initiering (lazy var) eller beräknade egenskaper (computed property).
Det mest kritiska misstaget — att använda @ObservedObject för att skapa ett objekt. Om du skriver @ObservedObject var model = UserViewModel() i föräldravyn kommer en ny UserViewModel-instans att skapas vid varje rendering. Data går förlorad och @Published-prenumerationer återskapas. Använd alltid @StateObject för att skapa och @ObservedObject endast för att ta emot ett färdigt objekt.
Andra misstaget — ändring av @Published-egenskaper utanför huvudtråden. ObservableObject använder Combine, som kräver att ändringar skickas på huvudtråden (main actor). Om du ändrar @Published i en bakgrundskö kan SwiftUI rita om vyn vid olämplig tidpunkt, vilket orsakar race conditions. Använd DispatchQueue.main.async eller @MainActor för uppdatering.
Tredje problemet — cykliska uppdateringar. Om en @Published-ändring inkluderar sidoeffekter som igen ändrar @Published uppstår en oändlig omritningsloop. Lösning: använd skyddsflaggor (isUpdating) eller dela upp logiken på olika ObservableObject med tydliga ansvarsgränser.
Vanliga frågor
Ja, SwiftUI stöder @ObservedObject var model: UserViewModel?. Vyn kommer dock inte att prenumerera på ändringar medan objektet är nil. När ett värde tilldelas aktiveras prenumerationen automatiskt.
@ObservedObject tar emot objektet via en initierare, @EnvironmentObject via SwiftUI Environment. @EnvironmentObject kräver inte explicit överföring via konstruktorer, men objektet måste injiceras på den övre nivån i hierarkin.
Anropa objectWillChange.send() före ändring av egenskapen. Detta är användbart om @Published inte är lämplig (till exempel för beräknade egenskaper eller samlingsoperationer där ändringen måste rapporteras före mutation).
@ObservedObject och @Published spårar referensersättning, inte mutation av samlingsinnehåll. För omritning måste du tilldela om arrayen: items.append(newItem) → items = items eller använda objectWillChange.send() före mutation.
Nej, @ObservedObject är en SwiftUI Property Wrapper som endast är tillgänglig inuti typer som implementerar View-protokollet. För vanliga strukturer, använd Combine direkt med ObservableObjectPublisher.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också