@ObservedObject: ce este, observarea obiectelor și actualizarea View

Autor: IT Sectr Publicat: 2026-06-26 Timp de citire: 9 min

@ObservedObject este un property wrapper în SwiftUI care permite unui View să observe modificările într-un ObservableObject creat în altă parte a ierarhiei. Spre deosebire de @StateObject, @ObservedObject nu creează un obiect — el doar se abonează la publisher-ul objectWillChange al acestuia și redesenează View-ul la actualizarea proprietăților @Published. Acest lucru face ca @ObservedObject să fie alegerea corectă pentru View-urile copil care primesc date de la părinte prin inițializator. Conform articolului lui Paul Hudson — Hacking with Swift (2025), arhitectura tipică a unei aplicații SwiftUI este construită astfel: View-ul rădăcină folosește @StateObject pentru a crea un view model, iar toate View-urile copil îl primesc prin @ObservedObject, asigurând o singură sursă de adevăr fără duplicare a datelor.

Principalele puncte

  • @ObservedObject — property wrapper pentru observarea unui ObservableObject creat în View-ul părinte.
  • Nu deține obiectul — spre deosebire de @StateObject, @ObservedObject nu gestionează ciclul de viață al obiectului.
  • Abonare la modificări — la modificarea proprietăților @Published, View-ul se redesenează automat.
  • Transmitere prin inițializator — obiectul este transmis în View-ul copil prin parametrul inițializatorului.
  • iOS 13+ — @ObservedObject este disponibil din prima versiune SwiftUI, spre deosebire de @StateObject (iOS 14+).

Ce este @ObservedObject în SwiftUI

@ObservedObject este un property wrapper care abonează View-ul la modificările ObservableObject. Când obiectul marcat cu @ObservedObject modifică oricare dintre proprietățile sale declarate cu @Published, SwiftUI redesenează automat View-ul. @ObservedObject nu creează obiectul — el doar stabilește o conexiune între o instanță existentă ObservableObject și View-ul care trebuie să reacționeze la modificările sale.

Diferența cheie între @ObservedObject și @StateObject — este proprietatea. @ObservedObject presupune că obiectul a fost creat și stocat undeva mai sus în ierarhia View-urilor. View-ul copil primește o referință la acest obiect prin inițializator și pur și simplu îl observă. Dacă View-ul copil este recreat, va primi aceeași referință de la părinte — datele nu se pierd.

Conform Apple Developer Documentation — SwiftUI (2025), @ObservedObject este disponibil începând cu iOS 13, ceea ce îl face singura opțiune pentru observarea ObservableObject în proiecte care suportă versiuni vechi de iOS. În iOS 14+ este preferat @StateObject pentru crearea obiectelor, dar @ObservedObject rămâne relevant pentru transmiterea obiectelor existente.

Cum funcționează @ObservedObject

Mecanismul @ObservedObject se bazează pe protocolul ObservableObject din framework-ul Combine. Fiecare clasă conformă cu ObservableObject primește automat un publisher objectWillChange care trimite un semnal înainte de modificarea oricărei proprietăți @Published. SwiftUI se abonează la acest publisher prin @ObservedObject și la primirea semnalului marchează View-ul ca necesitând redesenare.

swift
class TaskViewModel: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var isLoading = false
    
    func loadTasks() async {
        isLoading = true
        // încărcare date
        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() }
    }
}

Când View-ul părinte transmite viewModel către TaskListView prin inițializator, SwiftUI creează o conexiune între obiect și View. La modificarea array-ului tasks sau a flag-ului isLoading, SwiftUI redesenează TaskListView. Obiectul rămâne neschimbat — este stocat în View-ul părinte prin @StateObject.

@ObservedObject vs @StateObject: când să folosiți ce

Diferența între @ObservedObject și @StateObject — este diferența între observator și proprietar. @StateObject creează obiectul și gestionează ciclul său de viață. @ObservedObject doar observă obiectul care a fost creat și stocat în altă parte. Alegerea între ele este determinată de responsabilitatea View-ului pentru date.

ScenariuRecomandareMotiv
View-ul creează date@StateObjectView-ul deține obiectul și răspunde de ciclul său de viață
View-ul primește date@ObservedObjectView-ul doar observă, obiectul trăiește în părinte
Suport iOS 13@ObservedObject@StateObject indisponibil, utilizați @ObservedObject cu gestionare manuală
Component reutilizabil@ObservedObjectComponentul nu ar trebui să creeze date — le primește din exterior

Regula principală: dacă View-ul creează obiectul — @StateObject. Dacă View-ul primește obiectul — @ObservedObject. Încălcarea acestei reguli în favoarea @ObservedObject pentru crearea obiectului duce la pierderea datelor la reconstruirea View-ului. Încălcarea în favoarea @StateObject pentru primirea obiectului creează o instanță duplicată, independentă de părinte.

Exemple de utilizare @ObservedObject

Scenariul tipic de utilizare a @ObservedObject — o listă de sarcini, unde View-ul rădăcină creează un view model, iar celula listei îl primește prin @ObservedObject. Fiecare celulă poate apela metodele view model-ului, iar modificările sunt afișate automat în întreaga listă, deoarece toate celulele observă același obiect.

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

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

În acest exemplu TaskListContainer creează viewModel prin @StateObject, iar fiecare TaskRow îl primește prin @ObservedObject. Când utilizatorul apasă „Done” în orice rând, viewModel.completeTask modifică proprietatea published, iar toate View-urile care observă acest obiect se actualizează automat.

Erori tipice cu @ObservedObject

Cea mai frecventă eroare — utilizarea @ObservedObject pentru a crea un obiect în interiorul View-ului. Când View-ul este reconstruit (de exemplu, la modificarea stării), SwiftUI creează o nouă instanță ObservableObject, ceea ce duce la pierderea tuturor datelor acumulate. Această eroare este deosebit de dureroasă în NavigationStack, unde utilizatorul poate completa un formular și pierde datele la întoarcere.

Eroare: @ObservedObject în loc de @StateObject

swift
// ❌ Pierdere de date: @ObservedObject nu reține obiectul
struct FormView: View {
    @ObservedObject var formVM = FormViewModel()
    // FormVM nou creat la fiecare reconstruire a View-ului!
}

// ✅ Corect: @StateObject reține obiectul
struct FormView: View {
    @StateObject var formVM = FormViewModel()
    // Obiect creat o dată pe durata de viață a View-ului
}

Eroare: transmiterea @StateObject acolo unde este necesar @ObservedObject

Dacă View-ul copil declară același ObservableObject prin @StateObject, creează o copie independentă. Modificările în obiectul părinte nu vor fi vizibile în copil și invers. Folosiți întotdeauna @ObservedObject pentru View-urile copil care primesc obiectul din exterior.

Alternative la @ObservedObject în SwiftUI

În SwiftUI modern există mai multe alternative la @ObservedObject, fiecare cu avantajele sale. Alegerea depinde de arhitectura aplicației, versiunea iOS și scenariul specific de utilizare.

  • @EnvironmentObject — permite obținerea obiectului din mediul SwiftUI fără transmiterea explicită prin inițializator. Convenabil pentru obiecte necesare pe multe ecrane, dar necesită injectare explicită prin .environmentObject().
  • @State + @Binding — pentru tipuri de valoare simple nu sunt necesare ObservableObject. Folosiți @State pentru stocare și @Binding pentru transmiterea în View-urile copil.
  • @AppStorage — pentru valori UserDefaults care trebuie să se sincronizeze automat cu View-ul.
  • @SceneStorage — pentru salvarea stării temporare între repornirile scenei (de exemplu, poziția în listă).

Alegerea între @ObservedObject și @EnvironmentObject — este o chestiune de stil și arhitectură. @ObservedObject arată explicit dependențele View-ului prin inițializator, ceea ce face codul mai previzibil. @EnvironmentObject este convenabil pentru ierarhii adânci, dar ascunde dependențele, ceea ce poate îngreuna depanarea.

Întrebări frecvente

Se poate folosi @ObservedObject fără @StateObject în părinte?

Da, dacă obiectul este creat și stocat în afara SwiftUI — de exemplu, în AppDelegate sau singleton. În acest caz @ObservedObject pur și simplu se abonează la modificările obiectului existent. Cu toate acestea, pentru obiectele create în interiorul ierarhiei SwiftUI este întotdeauna necesar un @StateObject undeva mai sus.

De ce @ObservedObject uneori nu actualizează View-ul?

Cea mai probabilă cauză — proprietatea este modificată nu prin @Published sau nu se modifică obiectul în sine, ci structura sa internă fără apelarea objectWillChange. Pentru colecții folosiți atribuirea unei noi copii: array.append() nu este suficient — trebuie să reatribuiți întregul array prin array = array + [element].

@ObservedObject afectează performanța?

@ObservedObject în sine nu creează o sarcină semnificativă. Problemele apar la modificări frecvente ale proprietăților @Published — fiecare modificare declanșează redesenarea tuturor View-urilor observatoare. Pentru optimizare folosiți EquatableView, reduceți numărul de proprietăți published și evitați actualizările inutile.

Cu ce se deosebește @ObservedObject de @Binding?

@ObservedObject observă întreaga clasă ObservableObject și redesenează View-ul la orice modificare a proprietăților sale published. @Binding creează o conexiune bidirecțională cu o valoare specifică (String, Int, Bool) și permite citirea și scrierea acesteia. @Binding este mai ușor și nu necesită ObservableObject.

Se poate combina @ObservedObject cu @Published în aceeași clasă?

Da, acesta este un model standard. @Published în interiorul ObservableObject se integrează automat cu @ObservedObject. Fiecare proprietate @Published adaugă un observator la publisher-ul objectWillChange. La modificarea oricăreia dintre ele, toate View-urile cu @ObservedObject pentru acest obiect sunt redeseneate.

Rezumat

  • @ObservedObject — property wrapper pentru observarea ObservableObject creat în alt loc al ierarhiei.
  • Nu deține obiectul — spre deosebire de @StateObject, @ObservedObject nu gestionează ciclul de viață și nu creează obiectul.
  • Abonare prin Combine — SwiftUI se abonează automat la publisher-ul objectWillChange al ObservableObject.
  • iOS 13+ — @ObservedObject este disponibil din prima versiune SwiftUI, important pentru proiecte cu suport vechi.
  • Transmitere prin inițializator — obiectul este transmis explicit în View-ul copil, făcând dependențele transparente.
  • Eroare de proprietate — utilizarea @ObservedObject pentru a crea obiectul duce la pierderea datelor la reconstruirea View-ului.
  • Alternative — @EnvironmentObject pentru injectare prin mediu, @State/@Binding pentru tipuri de valoare.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și