@ObservedObject: ce este, cum funcționează și exemple

Autor: IT Sectr Publicat: 2026-06-19 Timp de citire: 7 min

@ObservedObject este un Property Wrapper în SwiftUI pentru observarea unei instanțe ObservableObject transmisă din exterior. Spre deosebire de @StateObject, @ObservedObject nu creează obiectul — se abonează la modificările unuia existent. Conform Apple Developer Documentation (2025), @ObservedObject este utilizat în view-urile copil care trebuie să urmărească date aparținând părintelui. @ObservedObject asigură o legătură reactivă fără gestionarea ciclului de viață al obiectului.

Principalele

  • @ObservedObject — Property Wrapper pentru observarea ObservableObject fără deținere
  • Fără creare — obiectul este transmis din view-ul părinte sau din mediu
  • @Published — proprietăți în ObservableObject ale căror modificări sunt urmărite de SwiftUI
  • Re-redare — la modificarea unei proprietăți @Published, SwiftUI actualizează toate view-urile abonate
  • Nu confundați cu @StateObject — @ObservedObject nu garantează o instanță unică

Ce este @ObservedObject în SwiftUI?

@ObservedObject este un Property Wrapper care abonează view-ul la modificările ObservableObject. ObservableObject este un protocol din framework-ul Combine care necesită implementarea publisher-ului objectWillChange. Când orice proprietate marcată cu @Published se modifică în ObservableObject, publisher-ul trimite un semnal, iar SwiftUI re-renderează toate view-urile abonate prin @ObservedObject.

Caracteristica principală a @ObservedObject este lipsa deținerii. View-ul nu este responsabil pentru crearea sau distrugerea obiectului. Obiectul este creat în view-ul părinte (prin @StateObject) sau injectat prin @EnvironmentObject. View-ul copil doar observă modificările și primește actualizări. Dacă obiectul este înlocuit în părinte, @ObservedObject comută pe noua instanță.

@ObservedObject este potrivit pentru scenarii de partajare a datelor: model de utilizator, setări comune, stare de conectare la server. Când mai multe view-uri la diferite niveluri ale ierarhiei trebuie să afișeze aceleași date, @ObservedObject în fiecare view creează abonamente independente, dar coerente la o singură sursă.

@ObservedObject vs @StateObject: diferențe cheie

Diferența dintre @ObservedObject și @StateObject este unul dintre cele mai frecvente subiecte la interviurile SwiftUI. Regula de bază: @StateObject creează și deține obiectul, @ObservedObject observă unul existent. Încălcarea acestei reguli duce la pierderea neașteptată a datelor sau inițializare dublă.

Caracteristică@StateObject@ObservedObject
Crearea obiectuluiDa, la inițializarea view-uluiNu, primește gata făcut
DeținereaView-ul curentComponenta părinte
Instanță unicăDa, pe întreg ciclul de viațăNu, poate fi înlocuit
Recreare la randareNu, se păstreazăDepinde de părinte
Unde se utilizeazăView-ul rădăcină deținătorView-uri copil

@StateObject garantează că obiectul este creat o singură dată și supraviețuiește inițializărilor repetate ale structurii view-ului. @ObservedObject primește obiectul din exterior și este recreat la fiecare inițializare a structurii părinte. Dacă părintele folosește @StateObject pentru obiect, view-urile copil pot utiliza în siguranță @ObservedObject — obiectul va fi unic în întreaga ierarhie.

Cum @ObservedObject urmărește modificările

Mecanismul de urmărire al @ObservedObject se bazează pe Combine și protocolul ObservableObject. La inițializare, SwiftUI apelează publisher-ul objectWillChange — obiectul trebuie să emită un semnal înainte de modificarea proprietății @Published. Combine transmite semnalul în graful de dependențe SwiftUI, care marchează toate view-urile dependente ca necesitând actualizare. Acest lucru se întâmplă sincron înainte de modificarea valorii.

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

În listingul WeatherService este un ObservableObject cu două proprietăți @Published. WeatherView declară @ObservedObject var weather: WeatherService, primind instanța de la părinte. Când temperature se modifică, objectWillChange se activează înainte de setarea noii valori, SwiftUI re-renderează WeatherView și se afișează temperatura actuală. Abonamentul este gestionat automat de SwiftUI — dezvoltatorul nu trebuie să apeleze sink sau dispose.

Modele de utilizare @ObservedObject

Primul model — transmiterea modelului prin inițializator. Părintele creează ObservableObject prin @StateObject și îl transmite view-urilor copil ca @ObservedObject. Aceasta este o transmitere ierarhică standard a datelor, în care view-ul rădăcină gestionează ciclul de viață al modelului, iar toate componentele imbricate se abonează la modificări.

Al doilea model — EnvironmentObject, versiunea globală a @ObservedObject prin SwiftUI Environment. Obiectul este injectat la nivelul scenei sau al view-ului rădăcină și este automat accesibil tuturor componentelor copil fără transmitere explicită prin inițializatori. În interiorul view-ului copil, @EnvironmentObject funcționează similar cu @ObservedObject, dar primește obiectul din mediu.

Al treilea model — compoziția mai multor ObservableObject. În aplicații complexe, view-ul poate observa mai multe obiecte: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. Aceasta separă responsabilitățile între servicii și păstrează testabilitatea fiecărui component.

swift
struct DashboardView: View {
    @ObservedObject var user: UserViewModel
    @ObservedObject var network: NetworkMonitor

    var body: some View {
        VStack {
            Text("Bun venit, \\(user.name)")
            HStack {
                Circle()
                    .fill(network.isConnected ? Color.green : Color.red)
                    .frame(width: 10, height: 10)
            }
        }
    }
}

DashboardView observă UserViewModel și NetworkMonitor. Fiecare obiect este responsabil pentru propriul domeniu de date și notifică independent view-ul despre modificări. Dacă rețeaua se deconectează, NetworkMonitor schimbă isConnected, iar SwiftUI re-renderează DashboardView, actualizând culoarea indicatorului. Compoziția ObservableObject este modul preferat de organizare a datelor în aplicațiile SwiftUI.

@Published: legătura ObservableObject și SwiftUI

@Published este un Property Wrapper din Combine care adaugă automat un editor la proprietatea din ObservableObject. Când proprietatea @Published se modifică, Combine generează un eveniment prin publisher-ul objectWillChange. SwiftUI se abonează la acest publisher când folosește @ObservedObject sau @StateObject și re-renderează view-ul la fiecare nouă valoare.

@Published suportă toate tipurile, inclusiv opționale, colecții și structuri personalizate. Totuși, pentru colecții (tablouri, dicționare) SwiftUI urmărește doar înlocuirea referinței, nu modificarea conținutului. Pentru a detecta adăugarea sau ștergerea unui element, trebuie reatribuită întreaga colecție sau folosit ObservableObject cu objectWillChange.send() manual.

Un detaliu important: @Published trebuie să se afle doar în interiorul unei clase care implementează ObservableObject. Utilizarea @Published în afara ObservableObject va cauza o eroare de compilare. De asemenea, @Published nu poate fi aplicat proprietăților cu inițializare lentă (lazy var) sau proprietăților calculate (computed property).

Erori tipice cu @ObservedObject

Cea mai critică eroare — utilizarea @ObservedObject pentru a crea un obiect. Dacă scrieți @ObservedObject var model = UserViewModel() în view-ul părinte, la fiecare randare va fi creată o nouă instanță UserViewModel. Datele se vor pierde, iar abonamentele @Published vor fi recreate. Utilizați întotdeauna @StateObject pentru creare și @ObservedObject doar pentru primirea unui obiect gata făcut.

A doua eroare — modificarea proprietăților @Published în afara firului principal. ObservableObject folosește Combine, care necesită trimiterea modificărilor pe firul principal (main actor). Dacă modificați @Published într-un fundal, SwiftUI poate re-rendera view-ul într-un moment nepotrivit, cauzând race conditions. Utilizați DispatchQueue.main.async sau @MainActor pentru actualizare.

A treia problemă — actualizări ciclice. Dacă o modificare @Published include efecte secundare care modifică din nou @Published, apare o buclă infinită de re-rendări. Soluție: utilizați flag-uri de protecție (isUpdating) sau separați logica pe diferite ObservableObject cu granițe clare de responsabilitate.

Întrebări frecvente

Poate @ObservedObject să fie opțional?

Da, SwiftUI suportă @ObservedObject var model: UserViewModel?. Totuși, view-ul nu va fi abonat la modificări cât timp obiectul este nil. La atribuirea valorii, abonamentul se activează automat.

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

@ObservedObject primește obiectul prin inițializator, @EnvironmentObject — prin SwiftUI Environment. @EnvironmentObject nu necesită transmitere explicită prin constructori, dar obiectul trebuie injectat la nivelul superior al ierarhiei.

Cum notific manual SwiftUI despre o modificare a ObservableObject?

Apelați objectWillChange.send() înainte de modificarea proprietății. Este util când @Published nu este potrivit (de exemplu, pentru proprietăți calculate sau operații cu colecții unde trebuie raportată modificarea înainte de mutație).

De ce @ObservedObject nu re-renderează view-ul la modificarea din interiorul unui tablou?

@ObservedObject și @Published urmăresc înlocuirea referinței, nu mutația conținutului colecției. Pentru re-rendare trebuie reatribuit tabloul: items.append(newItem) → items = items sau folosit objectWillChange.send() înainte de mutație.

Pot folosi @ObservedObject într-o structură care nu implementează View?

Nu, @ObservedObject este un Property Wrapper SwiftUI disponibil doar în tipurile care implementează protocolul View. Pentru structuri obișnuite, utilizați Combine direct cu ObservableObjectPublisher.

Concluzii

  • @ObservedObject — Property Wrapper pentru observarea ObservableObject fără deținere
  • @StateObject — creează obiectul, @ObservedObject — observă unul existent
  • @Published — editor automat pentru proprietățile ObservableObject
  • Abonament — SwiftUI gestionează automat abonamentul Combine când folosește @ObservedObject
  • Compoziție — view-ul poate observa mai multe ObservableObject simultan
  • Main actor — proprietățile @Published trebuie modificate doar pe firul principal
  • EnvironmentObject — alternativă la @ObservedObject pentru transmitere implicită prin mediu

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