@StateObject: co to je, vytvoření a správa ObservableObject

Autor: IT Sectr Publikováno: 2026-06-26 Doba čtení: 9 min

@StateObject je property wrapper ve SwiftUI, který vytváří a vlastní instanci ObservableObject po celou dobu životního cyklu View. Když se View poprvé objeví na obrazovce, @StateObject inicializuje objekt a uchovává jej, dokud není View odstraněno z paměti. To zaručuje, že data nebudou resetována při přestavbě rozhraní — například při změně motivu nebo aktualizaci nadřazeného View. Podle Apple Developer Documentation (2025) by měl být @StateObject používán jako hlavní zdroj pravdy (source of truth) pro ObservableObject v hierarchii SwiftUI, zatímco podřízené View získávají již vytvořený objekt prostřednictvím @ObservedObject nebo @EnvironmentObject.

Hlavní body

  • @StateObject — property wrapper pro vytvoření a vlastnictví ObservableObject uvnitř View.
  • Jednorázové vytvoření — objekt je inicializován jednou za dobu života View a není znovu vytvářen při přestavbách.
  • Source of truth — @StateObject je zdrojem pravdy v hierarchii, na rozdíl od @ObservedObject.
  • Životní cyklus — objekt žije, dokud View existuje v paměti, a je zničen společně s ním.
  • Inicializace — @StateObject vyžaduje počáteční hodnotu při vytvoření, obvykle pomocí init s parametry.

Co je @StateObject ve SwiftUI

@StateObject je property wrapper představený v iOS 14, který umožňuje View vytvářet a vlastnit instanci třídy vyhovující protokolu ObservableObject. Na rozdíl od @State, který pracuje s hodnotovými typy (strukturami), je @StateObject určen pro referenční typy — třídy, které mohou SwiftUI informovat o změnách svých vlastností.

Když View používá @StateObject var viewModel: MyViewModel, SwiftUI automaticky vytvoří instanci MyViewModel při prvním zobrazení View a uloží ji do speciálního úložiště frameworku. Při každé aktualizaci View (například při změně nadřazeného stavu) SwiftUI objekt znovu nevytváří — používá stávající instanci, dokud není View odstraněno z hierarchie.

Podle Apple WWDC Session 10137 (2024) řeší @StateObject problém ztráty dat při přestavbě View, který existoval v iOS 13, kdy vývojáři museli vytvářet ObservableObject v nadřazeném View a předávat jej přes inicializátor. To vedlo k duplikaci kódu a riziku náhodného znovuvytvoření objektu.

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("Počet: \(viewModel.count)")
            Button("Zvýšit", action: viewModel.increment)
        }
    }
}

Jak @StateObject funguje

Mechanismus @StateObject je založen na integraci SwiftUI s frameworkem Combine. Když ObservableObject označí své vlastnosti atributem @Published, SwiftUI se automaticky přihlásí ke změnám prostřednictvím publisheru vestavěného v protokolu ObservableObject. Při změně publikované vlastnosti objekt odešle signál přes publisher objectWillChange, což spustí překreslení všech View, která tento objekt pozorují.

SwiftUI ukládá instanci ObservableObject do speciálního úložiště vázaného na konkrétní instanci View. Toto úložiště je vytvořeno jednou při prvním renderování a existuje až do zničení View. Právě proto @StateObject zaručuje stabilitu reference na objekt — SwiftUI spravuje paměť automaticky, aniž by se spoléhal na inicializátor View.

Podle objc.io — Thinking in SwiftUI (2025) používá interní implementace @StateObject mechanismus podobný @State, ale pro referenční typy: SwiftUI vytváří boxing obal kolem objektu a spravuje jeho životní cyklus prostřednictvím vlastního alokátoru, optimalizovaného pro časté přestavby hierarchie View.

Životní cyklus @StateObject

  • Vytvoření — při prvním objevení View na obrazovce SwiftUI zavolá inicializátor objektu a uloží referenci.
  • Přestavba — při aktualizaci nadřazeného View není objekt znovu vytvářen, používá se stávající instance.
  • Zničení — když View opustí obrazovku a je odstraněno z hierarchie, SwiftUI zavolá deinit objektu.

@StateObject vs @ObservedObject: klíčové rozdíly

Hlavní rozdíl mezi @StateObject a @ObservedObject spočívá v tom, kdo objekt vlastní. @StateObject vytváří a ukládá objekt — je vlastníkem. @ObservedObject pouze pozoruje objekt, který byl vytvořen jinde a předán prostřednictvím inicializátoru nebo vlastnosti.

Vlastnost@StateObject@ObservedObject
VlastnictvíVytváří a vlastní objektPouze pozoruje
InicializaceUvnitř View pomocí init/defaultZvenčí, předáno parametrem
Životní cyklusVázán na životní cyklus ViewNení řízen View
ZnovuvytvořeníPři aktualizaci není znovu vytvářenMůže být nahrazen zvenčí
Verze iOSiOS 14+iOS 13+

Pravidlo je jednoduché: pokud View vytváří ObservableObject — použij @StateObject. Pokud View pouze přijímá již hotový objekt od rodiče — použij @ObservedObject. Porušení tohoto pravidla vede buď ke ztrátě dat (pokud použijete @ObservedObject pro vlastnictví), nebo k nadměrnému vytváření objektů (pokud použijete @StateObject pro pozorování).

Kdy použít @StateObject

@StateObject by měl být použit v těch View, která jsou zdrojem pravdy pro určitou sadu dat. Typické scénáře zahrnují obrazovky s vlastním view modelem, kořenové obrazovky navigačních zásobníků a modální prezentace spravující vlastní stav.

  • Obrazovka s view modelem — každá obrazovka, která spravuje vlastní data a logiku, by měla vytvářet svůj view model pomocí @StateObject.
  • Kořenový View — v hierarchii NavigationStack nebo TabView vytváří kořenový prvek data a podřízené prvky je získávají prostřednictvím @ObservedObject.
  • Modální okna — .sheet a .fullScreenCover často vyžadují vlastní @StateObject pro správu formuláře nebo procesu.
  • Seznam s úpravou — každý řádek seznamu obsahující editační formulář by měl mít vlastní @StateObject.
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("Uložit") {
                    viewModel.saveProfile()
                }
            }
            .navigationTitle("Profile")
        }
    }
}

Inicializace @StateObject s parametry

Inicializace @StateObject s parametry vyžaduje speciální syntaxi, protože SwiftUI spravuje vytváření objektu nezávisle. Nelze jednoduše předat parametry inicializátoru — je třeba použít escaping closure nebo samostatnou metodu vytvoření.

Podle Swift by Sundell (2024) je nejčistší metodou použití tovární metody nebo closure, kterou SwiftUI zavolá při prvním vytvoření objektu. Alternativní přístup — inicializovat ObservableObject v nadřazeném View a předat jej prostřednictvím @StateObject pomocí standardního inicializátoru.

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)
    }
}

Je důležité si pamatovat, že inicializátor View s @StateObject musí používat podtržítko před názvem vlastnosti (_viewModel) pro přístup k samotnému property wrapperu, nikoli k jeho hodnotě. Toto je standardní vzor Swift pro práci s property wrappery v inicializátorech.

Typické chyby s @StateObject

Nejčastější chybou je použití @ObservedObject místo @StateObject pro View, které by mělo objekt vlastnit. V tomto případě bude při každé přestavbě rodiče objekt znovu vytvořen, což vede ke ztrátě všech nashromážděných dat. Tato chyba je obzvláště záludná ve složitých hierarchiích s NavigationStack nebo TabView.

  • Ztráta dat při navigaci — pokud podřízená obrazovka používá @ObservedObject pro vlastní view model, při návratu a opětovném otevření budou data resetována.
  • Únik paměti — vytváření @StateObject v nadřazeném View, které není nikdy odstraněno, může vést k hromadění objektů, pokud každá podřízená obrazovka také vytváří @StateObject bez kontroly.
  • Duplikování objektů — předání jednoho ObservableObject několika @StateObject v různých View vytváří několik nezávislých instancí, které se vzájemně nesynchronizují.

Abyste se těmto problémům vyhnuli, dodržujte jednoduché pravidlo: jeden @StateObject na jeden zdroj pravdy. Pokud mají být data sdílena mezi více obrazovkami — vytvořte @StateObject jednou v kořenovém View a předávejte jej prostřednictvím @ObservedObject nebo @EnvironmentObject podřízeným prvkům.

swift
// ❌ Špatně: @ObservedObject pro vlastnictví objektu
struct BadView: View {
    @ObservedObject var vm = ViewModel() // bude znovu vytvořen při každé aktualizaci!
}

// ✅ Správně: @StateObject pro vlastnictví
struct GoodView: View {
    @StateObject var vm = ViewModel() // vytvořen jednou pro dobu života View
}

Často kladené dotazy

Jaký je rozdíl mezi @StateObject a @State?

@State pracuje s hodnotovými typy (struktury, řetězce, čísla) a ukládá hodnotu přímo do úložiště SwiftUI. @StateObject pracuje s referenčními typy — třídami vyhovujícími ObservableObject. @State je vhodný pro jednoduché lokální stavy, @StateObject pro složité objekty s logikou a publikovanými vlastnostmi.

Lze použít @StateObject v iOS 13?

Ne, @StateObject je dostupný pouze od iOS 14 výše. Pro iOS 13 použijte @ObservedObject a vytvářejte ObservableObject v nadřazeném View pomocí @State s ruční správou životního cyklu. Alternativou je použití @State se struct místo class pro data, která nevyžadují referenční sémantiku.

Co se stane, když použiji @StateObject v podřízeném View, do kterého je objekt předáván z rodiče?

Podřízené View vytvoří svou vlastní kopii ObservableObject, zcela nezávislou na rodičovské. Změny v jedné se neprojeví v druhé. To je téměř vždy chyba: použijte @ObservedObject pro příjem objektu od rodiče a @StateObject pouze pro vytvoření nového objektu uvnitř View.

Kdy je zničen objekt vytvořený prostřednictvím @StateObject?

Objekt je zničen, když View, které jej vytvořilo, je zcela odstraněno z hierarchie SwiftUI. Pro obrazovku v NavigationStack k tomu dochází při popu z navigačního zásobníku. Pro modální okno — při jeho zavření. Pro TabView — při přepnutí karty, pokud View není ukládáno do mezipaměti.

Jak předat parametry @StateObject při inicializaci?

Použijte vlastní init s přístupem k property wrapperu přes podtržítko: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Tento vzor umožňuje předat libovolné parametry ObservableObject při zachování záruky jediného vytvoření objektu po dobu života View.

Shrnutí

  • @StateObject — property wrapper pro vytvoření a vlastnictví ObservableObject uvnitř View, dostupný od iOS 14.
  • Záruka jediného vytvoření — objekt je inicializován jednou a není znovu vytvářen při přestavbě View.
  • Source of truth — @StateObject je zdrojem pravdy, @ObservedObject pouze pozorovatelem.
  • Životní cyklus — objekt žije, dokud View existuje v hierarchii SwiftUI, a je zničen při jejím opuštění.
  • Inicializace s parametry — vyžaduje přístup k property wrapperu přes _viewModel a StateObject(wrappedValue:).
  • Chyba vlastnictví — použití @ObservedObject pro vytvoření objektu vede ke ztrátě dat při přestavbě.
  • Jeden objekt — jeden @StateObject — pro sdílená data vytvořte @StateObject v kořenovém View a předávejte jej podřízeným přes @ObservedObject.

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í.

Prodiskutovat projekt

Přečtěte si také