@ObservedObject: cos'è, come funziona ed esempi

Autore: IT Sectr Pubblicato: 2026-06-19 Tempo di lettura: 7 min

@ObservedObject è un Property Wrapper in SwiftUI per osservare un'istanza ObservableObject passata dall'esterno. A differenza di @StateObject, @ObservedObject non crea un oggetto — si iscrive ai cambiamenti di uno già esistente. Secondo la Documentazione per Sviluppatori Apple (2025), @ObservedObject viene utilizzato nelle viste figlie che devono tracciare dati appartenenti al genitore. @ObservedObject fornisce una connessione reattiva senza gestire il ciclo di vita dell'oggetto.

Punti chiave

  • @ObservedObject — Property Wrapper per osservare ObservableObject senza possesso
  • Senza creazione — l'oggetto viene passato dalla vista genitore o dall'ambiente
  • @Published — proprietà all'interno di ObservableObject di cui SwiftUI traccia i cambiamenti
  • Riavvio — quando una proprietà @Published cambia, SwiftUI aggiorna tutte le viste iscritte
  • Da non confondere con @StateObject — @ObservedObject non garantisce un'istanza singola

Cos'è @ObservedObject in SwiftUI?

@ObservedObject è un Property Wrapper che iscrive una vista ai cambiamenti di un ObservableObject. ObservableObject è un protocollo del framework Combine che richiede l'implementazione di un publisher objectWillChange. Quando una proprietà contrassegnata con @Published cambia all'interno dell'ObservedObject, il publisher invia un segnale e SwiftUI riavvia tutte le viste iscritte tramite @ObservedObject.

La caratteristica principale di @ObservedObject è l'assenza di possesso. La vista non è responsabile della creazione o della distruzione dell'oggetto. L'oggetto viene creato nella vista genitore (tramite @StateObject) o iniettato tramite @EnvironmentObject. La vista figlia osserva solo i cambiamenti e riceve gli aggiornamenti. Se l'oggetto viene sostituito nel genitore, @ObservedObject passa alla nuova istanza.

@ObservedObject è adatto per scenari di condivisione dati: modello utente, impostazioni comuni, stato di connessione al server. Quando più viste a diversi livelli gerarchici devono mostrare gli stessi dati, @ObservedObject in ogni vista crea iscrizioni indipendenti ma coerenti a un'unica fonte.

@ObservedObject vs @StateObject: differenze chiave

La differenza tra @ObservedObject e @StateObject è uno degli argomenti più comuni nei colloqui su SwiftUI. La regola principale: @StateObject crea e possiede l'oggetto, @ObservedObject osserva uno già esistente. Violare questa regola porta a perdita imprevista di dati o doppia inizializzazione.

Caratteristica@StateObject@ObservedObject
Creazione oggettoSì, all'inizializzazione della vistaNo, riceve uno già pronto
PossessoVista correnteComponente genitore
Istanza singolaSì, per l'intero ciclo di vitaNo, può essere sostituita
Ricreazione al renderingNo, persisteDipende dal genitore
Dove usareVista radice proprietariaViste figlie

@StateObject garantisce che l'oggetto venga creato una volta e sopravviva a inizializzazioni ripetute della struttura della vista. @ObservedObject riceve l'oggetto dall'esterno e viene ricreato a ogni inizializzazione della struttura genitore. Se il genitore usa @StateObject per l'oggetto, le viste figlie possono applicare @ObservedObject in sicurezza — l'oggetto sarà unico nell'intera gerarchia.

Come @ObservedObject traccia i cambiamenti

Il meccanismo di tracciamento di @ObservedObject si basa su Combine e sul protocollo ObservableObject. Durante l'inizializzazione, SwiftUI chiama il publisher objectWillChange — l'oggetto deve emettere un segnale prima di modificare una proprietà @Published. Combine passa il segnale al grafo delle dipendenze di SwiftUI, che segna tutte le viste dipendenti come bisognose di aggiornamento. Questo avviene in modo sincrono prima che il valore cambi.

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

Nell'esempio, WeatherService è un ObservableObject con due proprietà @Published. WeatherView dichiara @ObservedObject var weather: WeatherService, ricevendo l'istanza dal genitore. Quando temperature cambia, objectWillChange si attiva prima di impostare il nuovo valore, SwiftUI riavvia WeatherView e viene visualizzata la temperatura attuale. L'iscrizione è gestita automaticamente da SwiftUI — lo sviluppatore non deve chiamare sink o dispose.

Pattern di utilizzo di @ObservedObject

Il primo pattern è il passaggio di un modello tramite l'inizializzatore. Il genitore crea un ObservableObject tramite @StateObject e lo passa alle viste figlie come @ObservedObject. Questo è un trasferimento dati gerarchico standard in cui la vista radice gestisce il ciclo di vita del modello e tutti i componenti annidati si iscrivono ai cambiamenti.

Il secondo pattern è EnvironmentObject, una versione globale di @ObservedObject tramite l'ambiente SwiftUI. L'oggetto viene iniettato a livello di scena o vista radice ed è automaticamente disponibile per tutti i componenti figli senza passaggio esplicito tramite inizializzatori. All'interno della vista figlia, @EnvironmentObject funziona in modo simile a @ObservedObject ma riceve l'oggetto dall'ambiente.

Il terzo pattern è la composizione di più ObservableObject. Nelle applicazioni complesse, una vista può osservare più oggetti: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. Questo separa le responsabilità tra i servizi e mantiene la testabilità di ogni componente.

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

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

DashboardView osserva UserViewModel e NetworkMonitor. Ogni oggetto gestisce il proprio dominio di dati e notifica indipendentemente la vista dei cambiamenti. Se la rete si disconnette, NetworkMonitor modifica isConnected e SwiftUI riavvia DashboardView, aggiornando il colore dell'indicatore. La composizione di ObservableObject è il metodo preferito per organizzare i dati nelle applicazioni SwiftUI.

@Published: il collegamento tra ObservableObject e SwiftUI

@Published è un Property Wrapper di Combine che aggiunge automaticamente un publisher a una proprietà all'interno di ObservableObject. Quando una proprietà @Published cambia, Combine genera un evento tramite il publisher objectWillChange. SwiftUI si iscrive a questo publisher quando usa @ObservedObject o @StateObject e riavvia la vista a ogni nuovo valore.

@Published supporta tutti i tipi, inclusi opzionali, collezioni e strutture personalizzate. Tuttavia, per le collezioni (array, dizionari), SwiftUI traccia solo la sostituzione del riferimento, non la mutazione del contenuto. Per rilevare l'aggiunta o la rimozione di un elemento, è necessario riassegnare l'intera collezione o usare ObservableObject con objectWillChange.send() manuale.

Un dettaglio importante: @Published deve essere usato solo all'interno di una classe che implementa ObservableObject. Usare @Published al di fuori di ObservableObject causerà un errore di compilazione. Inoltre, @Published non può essere applicato a proprietà di inizializzazione differita (lazy var) o proprietà calcolate.

Errori comuni con @ObservedObject

L'errore più critico è usare @ObservedObject per creare un oggetto. Se scrivi @ObservedObject var model = UserViewModel() nella vista genitore, ogni rendering creerà una nuova istanza di UserViewModel. I dati andranno persi e le iscrizioni @Published verranno ricreate. Usa sempre @StateObject per la creazione e @ObservedObject solo per ricevere un oggetto già pronto.

Il secondo errore è la modifica delle proprietà @Published al di fuori del thread principale. ObservableObject usa Combine, che richiede l'invio delle modifiche sul thread principale (main actor). Se modifichi @Published in una coda in background, SwiftUI potrebbe riavviare la vista in un momento inappropriato, causando race condition. Usa DispatchQueue.main.async o @MainActor per gli aggiornamenti.

Il terzo problema sono gli aggiornamenti ciclici. Se una modifica @Published innesca effetti collaterali che modificano nuovamente @Published, si verifica un ciclo infinito di riavvii. La soluzione: usare flag di protezione (isUpdating) o separare la logica in diversi ObservableObject con confini di responsabilità chiari.

Domande frequenti

@ObservedObject può essere opzionale?

Sì, SwiftUI supporta @ObservedObject var model: UserViewModel?. Tuttavia, la vista non si iscriverà ai cambiamenti finché l'oggetto è nil. Quando viene assegnato un valore, l'iscrizione si attiva automaticamente.

Qual è la differenza tra @ObservedObject e @EnvironmentObject?

@ObservedObject riceve l'oggetto tramite l'inizializzatore, @EnvironmentObject tramite l'ambiente SwiftUI. @EnvironmentObject non richiede passaggio esplicito tramite costruttori, ma l'oggetto deve essere iniettato al livello superiore della gerarchia.

Come notificare manualmente SwiftUI di un cambiamento di ObservableObject?

Chiama objectWillChange.send() prima di modificare la proprietà. Questo è utile quando @Published non è adatto (ad esempio, per proprietà calcolate o operazioni su collezioni dove è necessario segnalare il cambiamento prima della mutazione).

Perché @ObservedObject non riavvia la vista quando si modifica un array?

@ObservedObject e @Published tracciano la sostituzione del riferimento, non la mutazione del contenuto della collezione. Per attivare un riavvio, è necessario riassegnare l'array: items.append(newItem) → items = items o usare objectWillChange.send() prima della mutazione.

Si può usare @ObservedObject in una struct che non implementa View?

No, @ObservedObject è un Property Wrapper di SwiftUI disponibile solo all'interno di tipi che implementano il protocollo View. Per le struct normali, usa Combine direttamente con ObservableObjectPublisher.

Riepilogo

  • @ObservedObject — Property Wrapper per osservare ObservableObject senza possesso
  • @StateObject — crea l'oggetto, @ObservedObject — osserva uno esistente
  • @Published — publisher automatico per le proprietà ObservableObject
  • Iscrizione — SwiftUI gestisce automaticamente l'iscrizione Combine quando si usa @ObservedObject
  • Composizione — una vista può osservare più ObservableObject simultaneamente
  • Main actor — le proprietà @Published dovrebbero essere modificate solo sul thread principale
  • EnvironmentObject — un'alternativa a @ObservedObject per il passaggio implicito tramite l'ambiente

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche