@ObservedObject: cos’è, osservazione di oggetti e aggiornamento delle View

Autore: IT Sectr Pubblicato: 2026-06-26 Tempo di lettura: 9 min

@ObservedObject è un property wrapper in SwiftUI che consente a una View di osservare i cambiamenti in un ObservableObject creato altrove nella gerarchia. A differenza di @StateObject, @ObservedObject non crea l’oggetto — si sottoscrive solo al suo publisher objectWillChange e ridisegna la View quando le proprietà pubblicate vengono aggiornate. Questo rende @ObservedObject la scelta corretta per le View figlie che ricevono dati da un genitore tramite un inizializzatore. Secondo un articolo di Paul Hudson — Hacking with Swift (2025), un’architettura tipica di un’app SwiftUI si costruisce così: la View radice usa @StateObject per creare un view model, e tutte le View figlie lo ricevono tramite @ObservedObject, garantendo un’unica fonte di verità senza duplicazione di dati.

Punti chiave

  • @ObservedObject — un property wrapper per osservare un ObservableObject creato in una View genitore.
  • Non possiede l’oggetto — a differenza di @StateObject, @ObservedObject non gestisce il ciclo di vita dell’oggetto.
  • Si sottoscrive ai cambiamenti — quando le proprietà @Published cambiano, la View si ridisegna automaticamente.
  • Passato tramite inizializzatore — l’oggetto viene passato alla View figlia tramite un parametro dell’inizializzatore.
  • iOS 13+ — @ObservedObject è disponibile dalla prima versione di SwiftUI, a differenza di @StateObject (iOS 14+).

Cos’è @ObservedObject in SwiftUI

@ObservedObject è un property wrapper che sottoscrive una View ai cambiamenti ObservableObject. Quando un oggetto marcato con @ObservedObject modifica una qualsiasi delle sue proprietà dichiarate con @Published, SwiftUI ridisegna automaticamente la View. @ObservedObject non crea l’oggetto — stabilisce solo una connessione tra un’istanza ObservableObject esistente e la View che deve reagire ai suoi cambiamenti.

La differenza chiave tra @ObservedObject e @StateObject è la proprietà. @ObservedObject presuppone che l’oggetto sia creato e memorizzato più in alto nella gerarchia delle View. La View figlia riceve un riferimento a questo oggetto tramite l’inizializzatore e semplicemente lo osserva. Se la View figlia viene ricreata, riceve lo stesso riferimento dal genitore — i dati non vengono persi.

Secondo la Documentazione Apple Developer — SwiftUI (2025), @ObservedObject è disponibile a partire da iOS 13, rendendolo l’unica opzione per osservare ObservableObject in progetti che supportano versioni iOS precedenti. In iOS 14+, @StateObject è preferito per creare oggetti, ma @ObservedObject rimane rilevante per passare oggetti esistenti.

Come funziona @ObservedObject

Il meccanismo di @ObservedObject si basa sul protocollo ObservableObject del framework Combine. Ogni classe conforme a ObservableObject ottiene automaticamente un publisher objectWillChange che invia un segnale prima di qualsiasi modifica a una proprietà @Published. SwiftUI si sottoscrive a questo publisher tramite @ObservedObject e, al ricevimento del segnale, marca la View come bisognosa di ridisegno.

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

Quando la View genitore passa viewModel a TaskListView tramite l’inizializzatore, SwiftUI crea una connessione tra l’oggetto e la View. Quando l’array tasks o il flag isLoading cambiano, SwiftUI ridisegna TaskListView. L’oggetto stesso rimane invariato — viene memorizzato nella View genitore tramite @StateObject.

@ObservedObject vs @StateObject: quando usare cosa

La differenza tra @ObservedObject e @StateObject è la differenza tra un osservatore e un proprietario. @StateObject crea l’oggetto e gestisce il suo ciclo di vita. @ObservedObject osserva solo un oggetto che è stato creato e memorizzato altrove. La scelta tra di essi è determinata dalla responsabilità della View verso i dati.

ScenarioRaccomandazioneMotivo
La View crea dati@StateObjectLa View possiede l’oggetto ed è responsabile del suo ciclo di vita
La View riceve dati@ObservedObjectLa View osserva solo, l’oggetto vive nel genitore
Supporto iOS 13@ObservedObject@StateObject non disponibile, usa @ObservedObject con gestione manuale
Componente riutilizzabile@ObservedObjectIl componente non deve creare dati — li riceve esternamente

La regola principale: se la View crea l’oggetto — @StateObject. Se la View riceve l’oggetto — @ObservedObject. Violare questa regola usando @ObservedObject per creare un oggetto porta alla perdita di dati quando la View viene ricostruita. Violarla usando @StateObject per ricevere un oggetto crea un’istanza duplicata indipendente dal genitore.

Esempi di utilizzo di @ObservedObject

Uno scenario tipico di utilizzo di @ObservedObject è un elenco di attività in cui la View radice crea un view model e ogni cella dell’elenco lo riceve tramite @ObservedObject. Ogni cella può chiamare metodi del view model, e i cambiamenti si riflettono automaticamente sull’intero elenco poiché tutte le celle osservano lo stesso oggetto.

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

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

In questo esempio, TaskListContainer crea viewModel tramite @StateObject, e ogni TaskRow lo riceve tramite @ObservedObject. Quando l’utente preme “Done” in qualsiasi riga, viewModel.completeTask modifica una proprietà pubblicata, e tutte le View che osservano questo oggetto si aggiornano automaticamente.

Errori comuni con @ObservedObject

L’errore più comune è usare @ObservedObject per creare un oggetto all’interno di una View. Quando la View viene ricostruita (ad esempio, quando lo stato cambia), SwiftUI crea una nuova istanza ObservableObject, portando alla perdita di tutti i dati accumulati. Questo errore è particolarmente doloroso in NavigationStack, dove un utente potrebbe compilare un modulo e perdere i dati tornando indietro.

Errore: @ObservedObject invece di @StateObject

swift
// ❌ Perdita dati: @ObservedObject non trattiene l’oggetto
struct FormView: View {
    @ObservedObject var formVM = FormViewModel()
    // Nuovo formVM creato ad ogni ricostruzione della View!
}

// ✅ Corretto: @StateObject trattiene l’oggetto
struct FormView: View {
    @StateObject var formVM = FormViewModel()
    // Oggetto creato una volta per durata della View
}

Errore: passare @StateObject dove serve @ObservedObject

Se una View figlia dichiara lo stesso ObservableObject tramite @StateObject, crea una copia indipendente. I cambiamenti nell’oggetto genitore non saranno visibili nella figlia, e viceversa. Usa sempre @ObservedObject per le View figlie che ricevono l’oggetto esternamente.

Alternative a @ObservedObject in SwiftUI

In SwiftUI moderno esistono diverse alternative a @ObservedObject, ciascuna con i propri vantaggi. La scelta dipende dall’architettura dell’applicazione, dalla versione di iOS e dal caso d’uso specifico.

  • @EnvironmentObject — consente di ottenere un oggetto dall’ambiente SwiftUI senza passarlo esplicitamente tramite l’inizializzatore. Comodo per oggetti necessari a molti schermi, ma richiede iniezione esplicita tramite .environmentObject().
  • @State + @Binding — per tipi di valore semplici, ObservableObject non è necessario. Usa @State per la memorizzazione e @Binding per il passaggio alle View figlie.
  • @AppStorage — per valori UserDefaults che devono sincronizzarsi automaticamente con la View.
  • @SceneStorage — per preservare lo stato temporaneo tra riavvii di scena (ad esempio, posizione di scorrimento in un elenco).

La scelta tra @ObservedObject e @EnvironmentObject è una questione di stile e architettura. @ObservedObject mostra esplicitamente le dipendenze della View tramite l’inizializzatore, rendendo il codice più prevedibile. @EnvironmentObject è comodo per gerarchie profonde ma nasconde le dipendenze, il che può complicare il debugging.

Domande frequenti

Si può usare @ObservedObject senza @StateObject nel genitore?

Sì, se l’oggetto è creato e memorizzato al di fuori di SwiftUI — ad esempio, in un AppDelegate o singleton. In questo caso, @ObservedObject si sottoscrive semplicemente ai cambiamenti di un oggetto esistente. Tuttavia, per oggetti creati all’interno della gerarchia SwiftUI, @StateObject è sempre necessario a qualche livello superiore.

Perché @ObservedObject a volte non aggiorna la View?

La ragione più probabile è che la proprietà viene modificata non tramite @Published o che l’oggetto stesso non viene modificato ma la sua struttura interna muta senza chiamare objectWillChange. Per le collezioni, usa l’assegnazione di una nuova copia: array.append() non basta — devi riassegnare l’array stesso tramite array = array + [element].

@ObservedObject influisce sulle prestazioni?

@ObservedObject di per sé non crea un overhead significativo. I problemi sorgono con cambiamenti frequenti delle proprietà @Published — ogni cambiamento attiva un ridisegno di tutte le View osservatrici. Per ottimizzare, usa EquatableView, riduci il numero di proprietà pubblicate ed evita aggiornamenti non necessari.

Qual è la differenza tra @ObservedObject e @Binding?

@ObservedObject osserva un’intera classe ObservableObject e ridisegna la View ad ogni cambiamento delle sue proprietà pubblicate. @Binding crea una connessione bidirezionale con un valore specifico (String, Int, Bool) e consente di leggerlo e scriverlo. @Binding è più leggero e non richiede ObservableObject.

Si può combinare @ObservedObject con @Published nella stessa classe?

Sì, questo è il pattern standard. @Published all’interno di ObservableObject si integra automaticamente con @ObservedObject. Ogni proprietà @Published aggiunge un osservatore al publisher objectWillChange. Quando una di esse cambia, tutte le View con @ObservedObject per questo oggetto vengono ridisegnate.

Riepilogo

  • @ObservedObject — un property wrapper per osservare un ObservableObject creato altrove nella gerarchia.
  • Non possiede l’oggetto — a differenza di @StateObject, @ObservedObject non gestisce il ciclo di vita né crea l’oggetto.
  • Sottoscrizione tramite Combine — SwiftUI si sottoscrive automaticamente al publisher objectWillChange dell’ObservableObject.
  • iOS 13+ — @ObservedObject è disponibile dalla prima versione di SwiftUI, importante per progetti con supporto legacy.
  • Passato tramite inizializzatore — l’oggetto viene passato esplicitamente alla View figlia, rendendo le dipendenze trasparenti.
  • Errore di proprietà — usare @ObservedObject per creare un oggetto porta alla perdita di dati quando la View viene ricostruita.
  • Alternative — @EnvironmentObject per iniezione ambientale, @State/@Binding per tipi di valore.

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