@ObservedObject je Property Wrapper ve SwiftUI pro pozorování instance ObservableObject předané zvenčí. Na rozdíl od @StateObject, @ObservedObject objekt nevytváří — přihlašuje se ke změnám již existujícího. Podle Apple Developer Documentation (2025) se @ObservedObject používá v podřízených view, která potřebují sledovat data patřící rodiči. @ObservedObject poskytuje reaktivní spojení bez správy životního cyklu objektu.
Hlavní
@ObservedObject je Property Wrapper, který přihlašuje view ke změnám ObservableObject. ObservableObject je protokol z frameworku Combine, který vyžaduje implementaci publisheru objectWillChange. Když se jakákoli vlastnost označená @Published změní uvnitř ObservableObject, publisher odešle signál a SwiftUI překreslí všechna view přihlášená přes @ObservedObject.
Hlavní vlastností @ObservedObject je absence vlastnictví. View není odpovědné za vytvoření nebo zničení objektu. Objekt je vytvořen v rodičovském view (přes @StateObject) nebo vložen přes @EnvironmentObject. Podřízené view pouze pozoruje změny a přijímá aktualizace. Pokud je objekt v rodiči nahrazen, @ObservedObject přepne na novou instanci.
@ObservedObject je vhodný pro scénáře sdílení dat: model uživatele, společná nastavení, stav připojení k serveru. Když několik view na různých úrovních hierarchie musí zobrazovat stejná data, @ObservedObject v každém view vytváří nezávislá, ale koordinovaná přihlášení k jednomu zdroji.
Rozdíl mezi @ObservedObject a @StateObject je jedním z nejčastějších témat otázek na pohovorech o SwiftUI. Základní pravidlo: @StateObject vytváří a vlastní objekt, @ObservedObject pozoruje již existující. Porušení tohoto pravidla vede k neočekávané ztrátě dat nebo dvojité inicializaci.
| Charakteristika | @StateObject | @ObservedObject |
|---|---|---|
| Vytvoření objektu | Ano, při inicializaci view | Ne, přijímá hotový |
| Vlastnictví | Aktuální view | Rodičovská komponenta |
| Jediná instance | Ano, po celý životní cyklus | Ne, může být nahrazena |
| Znovuvytvoření při renderu | Ne, zachovává se | Závisí na rodiči |
| Kde použít | Kořenové view-vlastník | Podřízená view |
@StateObject zaručuje, že objekt je vytvořen jednou a přežije opakované inicializace struktury view. @ObservedObject přijímá objekt zvenčí a je znovu vytvořen při každé inicializaci rodičovské struktury. Pokud rodič používá @StateObject pro objekt, podřízená view mohou bezpečně aplikovat @ObservedObject — objekt bude v celé hierarchii jedinečný.
Mechanismus sledování @ObservedObject je založen na Combine a protokolu ObservableObject. Při inicializaci SwiftUI volá publisher objectWillChange — objekt musí vyslat signál před změnou @Published vlastnosti. Combine předá signál do grafu závislostí SwiftUI, který označí všechna závislá view jako vyžadující aktualizaci. To se děje synchronně před změnou hodnoty.
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")
}
}
}
Ve výpisu je WeatherService ObservableObject se dvěma @Published vlastnostmi. WeatherView deklaruje @ObservedObject var weather: WeatherService, přičemž instanci získává od rodiče. Když se temperature změní, objectWillChange se aktivuje před nastavením nové hodnoty, SwiftUI překreslí WeatherView a zobrazí se aktuální teplota. Přihlášení je automaticky spravováno SwiftUI — vývojář nemusí volat sink ani dispose.
První vzor — předání modelu přes inicializátor. Rodič vytvoří ObservableObject přes @StateObject a předá jej podřízeným view jako @ObservedObject. Toto je standardní hierarchické předávání dat, kde kořenové view spravuje životní cyklus modelu a všechny vnořené komponenty se přihlašují ke změnám.
Druhý vzor — EnvironmentObject, globální verze @ObservedObject přes SwiftUI Environment. Objekt je vložen na úrovni scény nebo kořenového view a je automaticky dostupný všem podřízeným komponentám bez explicitního předávání přes inicializátory. Uvnitř podřízeného view funguje @EnvironmentObject podobně jako @ObservedObject, ale získává objekt z prostředí.
Třetí vzor — kompozice více ObservableObject. Ve složitých aplikacích může view pozorovat více objektů: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. To rozděluje odpovědnost mezi služby a zachovává testovatelnost každé komponenty.
struct DashboardView: View {
@ObservedObject var user: UserViewModel
@ObservedObject var network: NetworkMonitor
var body: some View {
VStack {
Text("Vítejte, \\(user.name)")
HStack {
Circle()
.fill(network.isConnected ? Color.green : Color.red)
.frame(width: 10, height: 10)
}
}
}
}
DashboardView pozoruje UserViewModel a NetworkMonitor. Každý objekt je odpovědný za svou doménu dat a nezávisle informuje view o změnách. Pokud se síť odpojí, NetworkMonitor změní isConnected a SwiftUI překreslí DashboardView a aktualizuje barvu indikátoru. Kompozice ObservableObject je preferovaný způsob organizace dat v aplikacích SwiftUI.
@Published je Property Wrapper z Combine, který automaticky přidává vydavatele k vlastnosti uvnitř ObservableObject. Když se @Published vlastnost změní, Combine vygeneruje událost přes publisher objectWillChange. SwiftUI se k tomuto publisheru přihlásí při použití @ObservedObject nebo @StateObject a překreslí view při každé nové hodnotě.
@Published podporuje všechny typy, včetně volitelných, kolekcí a vlastních struktur. U kolekcí (pole, slovníky) však SwiftUI sleduje pouze nahrazení reference, nikoli změnu obsahu. Pro detekci přidání nebo odebrání prvku je třeba znovu přiřadit celou kolekci nebo použít ObservableObject s ručním objectWillChange.send().
Důležitý detail: @Published se musí nacházet pouze uvnitř třídy implementující ObservableObject. Použití @Published mimo ObservableObject způsobí chybu kompilace. Také @Published nelze aplikovat na vlastnosti s línou inicializací (lazy var) nebo vypočítané vlastnosti (computed property).
Nejkritičtější chyba — použití @ObservedObject k vytvoření objektu. Pokud napíšete @ObservedObject var model = UserViewModel() v rodičovském view, při každém renderu bude vytvořena nová instance UserViewModel. Data budou ztracena a @Published přihlášení budou znovu vytvořena. Vždy používejte @StateObject pro vytvoření a @ObservedObject pouze pro příjem hotového objektu.
Druhá chyba — změna @Published vlastností mimo hlavní vlákno. ObservableObject používá Combine, který vyžaduje odesílání změn na hlavním vlákně (main actor). Pokud změníte @Published v běžné frontě na pozadí, SwiftUI může překreslit view v nevhodnou chvíli, což způsobí race conditions. Pro aktualizaci použijte DispatchQueue.main.async nebo @MainActor.
Třetí problém — cyklické aktualizace. Pokud změna @Published zahrnuje vedlejší účinky, které znovu změní @Published, vznikne nekonečná smyčka překreslování. Řešení: používejte ochranné příznaky (isUpdating) nebo rozdělte logiku na různé ObservableObject s jasnými hranicemi odpovědnosti.
Často kladené otázky
Ano, SwiftUI podporuje @ObservedObject var model: UserViewModel?. View se však nebude přihlašovat ke změnám, dokud je objekt nil. Při přiřazení hodnoty se přihlášení automaticky aktivuje.
@ObservedObject přijímá objekt přes inicializátor, @EnvironmentObject přes SwiftUI Environment. @EnvironmentObject nevyžaduje explicitní předávání přes konstruktory, ale objekt musí být vložen na horní úrovni hierarchie.
Zavolejte objectWillChange.send() před změnou vlastnosti. To je užitečné, pokud @Published není vhodný (například pro vypočítané vlastnosti nebo operace s kolekcemi, kde je třeba ohlásit změnu před mutací).
@ObservedObject a @Published sledují nahrazení reference, nikoli mutaci obsahu kolekce. Pro překreslení je třeba znovu přiřadit pole: items.append(newItem) → items = items nebo použít objectWillChange.send() před mutací.
Ne, @ObservedObject je Property Wrapper SwiftUI dostupný pouze uvnitř typů implementujících protokol View. Pro běžné struktury použijte Combine přímo s ObservableObjectPublisher.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také