.onAppear: principio di funzionamento, ciclo di vita ed esempi in SwiftUI

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

.onAppear è un modificatore SwiftUI che esegue una closure quando una View viene aggiunta alla gerarchia dell’interfaccia. La chiamata avviene una volta per apparizione dell’istanza sullo schermo e funge da punto principale per caricare dati, avviare animazioni e inviare eventi di analisi. Secondo la Apple Developer Documentation (2026), onAppear garantisce l’esecuzione prima del primo rendering, ma non garantisce la chiamata a ogni visualizzazione ripetuta se la View rimane in memoria. Ulteriori informazioni su SwiftUI nell’articolo su SwiftUI.

Punti chiave

  • .onAppear è un modificatore SwiftUI per eseguire codice quando una View appare sullo schermo.
  • Esecuzione singola — onAppear viene chiamato una volta per ciclo di vita della View se rimane in memoria.
  • Caricamento dati — il caso d’uso principale di onAppear: fetch da API, lettura da Core Data o UserDefaults.
  • Animazioni — onAppear avvia animazioni di ingresso: opacity, scale, offset con ritardo.
  • Analytics — gli eventi screen view, impression, page open vengono inviati tramite onAppear.

Cos’è .onAppear?

.onAppear è un modificatore di View in SwiftUI che accetta una closure Void e la esegue quando la View diventa visibile sullo schermo. Questo modificatore fa parte del sistema del ciclo di vita dei componenti SwiftUI insieme a .onDisappear e .task. Apple ha introdotto onAppear con il rilascio di SwiftUI in iOS 13 e watchOS 6 come sostituto di viewDidLoad di UIKit.

Sintatticamente, .onAppear modifica qualsiasi View e restituisce la stessa View con un’azione allegata. Il compositore SwiftUI chiama la closure passata una volta quando la view viene aggiunta alla gerarchia e supera la fase di rendering. Se una View viene rimossa e poi aggiunta di nuovo (ad esempio, scorrendo in un elenco), onAppear viene chiamato di nuovo — questo comportamento diventa spesso fonte di bug imprevisti.

Sintassi di onAppear

La sintassi di base del modificatore è minimalista: onAppear senza parametri. SwiftUI non offre alcun modo per passare priorità o animazione — la closure viene eseguita in modo sincrono sul thread principale immediatamente dopo il rendering.

swift
struct ContentView: View {
    var body: some View {
        Text("Hello, SwiftUI!")
            .onAppear {
                print("View appeared on screen")
            }
    }
}

Limitazioni: onAppear non supporta async/await direttamente. Per operazioni asincrone all’interno della closure, è necessario Task {} o una funzione async/await separata chiamata tramite Task.detached. Ciò rende onAppear meno conveniente per le richieste di rete rispetto al modificatore .task.

Come funziona .onAppear nel ciclo di vita di View

.onAppear è incorporato nella pipeline di rendering di SwiftUI nella fase layout+render. Quando SwiftUI calcola il corpo della View e rileva un cambiamento nella gerarchia, attiva i callback onAppear per tutte le view appena aggiunte. L’ordine di chiamata segue l’annidamento: onAppear del genitore prima, poi gli elementi figli.

Una caratteristica importante di SwiftUI è che onAppear non è legato all’apparizione fisica sullo schermo. Il modificatore viene chiamato quando una View viene aggiunta alla gerarchia, indipendentemente dal fatto che sia visibile all’utente (ad esempio, fuori schermo in una ScrollView). Questo distingue SwiftUI da UIKit, dove viewWillAppear viene attivato solo all’apparizione effettiva.

Ordine di chiamata di onAppear

L’ordine di chiamata segue la regola genitore-primo: VStack o NavigationView riceve onAppear per primo, poi ogni elemento figlio in ordine. Ciò è fondamentale per l’inizializzazione delle risorse condivise: se gli elementi figli dipendono dai dati caricati dal genitore, devono verificare la disponibilità tramite Optional.

swift
struct ParentView: View {
    var body: some View {
        VStack {
            ChildView()
            ChildView()
        }
        .onAppear {
            print("Parent onAppear — first")
        }
    }
}

struct ChildView: View {
    var body: some View {
        Text("Child")
            .onAppear {
                print("Child onAppear")
            }
    }
}

L’output della console sarà: Parent onAppear — primo, poi Child onAppear due volte in ordine. Questo comportamento è garantito da Apple e stabile in tutte le versioni di SwiftUI (iOS 13–18).

Quando viene chiamato .onAppear

.onAppear ha diversi scenari di chiamata che dipendono dal contenitore e dalla navigazione. In NavigationStack, onAppear viene attivato a ogni push di un nuovo controller e al pop — per il controller radice. In TabView, il cambio di scheda chiama onAppear per la scheda visualizzata e onDisappear per quella nascosta.

In List e ScrollView, onAppear viene chiamato per le celle che sono entrate nell’area visibile o si trovano nel buffer di pre-rendering. iOS 18 ha introdotto un meccanismo di prefetch che può chiamare onAppear per le celle 2–3 schermi prima dello scorrimento — questo accelera la percezione ma può provocare richieste di rete non necessarie.

Comportamento di chiamata in NavigationStack

NavigationStack (iOS 16+) gestisce lo stack di schermi in modo diverso da NavigationView. Quando si fa push di un nuovo schermo, onAppear viene attivato solo sul nuovo schermo, mentre quello corrente non riceve onDisappear fino alla rimozione effettiva. Al pop, avviene il processo inverso: onDisappear sullo schermo che si abbandona, onAppear su quello che ritorna.

ScenarioonAppearonDisappear
PushNuovo schermoNo (lo schermo rimane nello stack)
PopSchermo di ritornoSchermo abbandonato
Cambio schedaNuova schedaVecchia scheda
Chiusura sheetSchermo genitoreSheet aperto

Esempi di utilizzo di .onAppear

Le applicazioni pratiche di onAppear coprono tre categorie principali: caricamento dati, avvio animazioni e invio di analisi. Ogni scenario richiede la considerazione delle caratteristiche del ciclo di vita di SwiftUI per evitare chiamate duplicate e perdite di memoria.

Caricamento dati da API

Il caricamento dati è il caso d’uso più comune di onAppear. All’interno della closure, viene creato un Task per la chiamata async e il risultato viene memorizzato in @State o @StateObject. È importante verificare se i dati sono già stati caricati utilizzando un flag isLoading o un controllo nil.

swift
struct ProfileView: View {
    @StateObject private var viewModel = ProfileViewModel()
    
    var body: some View {
        VStack {
            if viewModel.isLoading {
                ProgressView()
            } else {
                Text(viewModel.userName)
            }
        }
        .onAppear {
            guard viewModel.userName == nil else { return }
            Task {
                await viewModel.loadProfile()
            }
        }
    }
}

La protezione contro il re-fetch è una pratica critica. Se SwiftUI ricrea la View (ad esempio, alla rotazione dello schermo), onAppear si attiverà di nuovo senza protezione. Un’alternativa è il modificatore .task, che annulla automaticamente la richiesta precedente.

Avvio dell’animazione di ingresso

L’animazione di ingresso utilizza onAppear per modificare le variabili di stato che attivano l’animazione tramite withAnimation o il modificatore animation. Schema tipico: stato iniziale (opacity 0, offset 100), transizione allo stato finale (opacity 1, offset 0) all’apparizione.

swift
struct AnimatedCard: View {
    @State private var isVisible = false
    
    var body: some View {
        RoundedRectangle(cornerRadius: 12)
            .fill(Color.blue)
            .opacity(isVisible ? 1 : 0)
            .offset(y: isVisible ? 0 : 50)
            .animation(.spring(), value: isVisible)
            .onAppear {
                withAnimation(.spring().delay(0.3)) {
                    isVisible = true
                }
            }
    }
}

Il ritardo di 0,3 secondi crea un effetto di apparizione sequenziale se ci sono più carte sullo schermo. Per un elenco di elementi animati, utilizzare l’indice dell’elemento come moltiplicatore di ritardo.

.onAppear vs .task — differenze

.task è un modificatore SwiftUI aggiunto in iOS 15 che risolve il problema delle operazioni asincrone in onAppear. A differenza di onAppear, .task accetta una closure async, gestisce automaticamente il suo ciclo di vita e la annulla quando la View scompare. Mentre onAppear viene eseguito in modo sincrono, .task avvia un’operazione asincrona e permette a SwiftUI di annullarla in onDisappear.

La differenza principale è la gestione dell’annullamento. Quando .task crea un’operazione async, SwiftUI salva un riferimento al Task e chiama automaticamente cancel() quando la View viene rimossa dalla gerarchia. onAppear con Task {} all’interno non annulla l’operazione in esecuzione — continua anche dopo che la View è scomparsa, il che può causare condizioni di competizione o scritture in un’istanza deallocata.

Caratteristica.onAppear.task
Versione iOSiOS 13+iOS 15+
Supporto asyncSolo tramite Task {}Async/await nativo
Auto-annullamentoNoAlla scomparsa della View
RichiamataA ogni apparizioneSingola per default
Codice sincronoSolo async

Scelta del modificatore: per azioni sincrone (animazioni, analisi, logging) usa onAppear. Per il caricamento asincrono di dati (API, Core Data, file system) preferisci .task — è più sicuro e pulito.

Errori comuni con .onAppear

Errore 1: chiamate multiple dovute alla ricreazione della View. Quando SwiftUI ricrea il corpo della View (cambio di stato, rotazione dello schermo), onAppear può essere chiamato di nuovo. Soluzione — aggiungi un flag di caricamento o usa .equatable() per prevenire ridisegni non necessari. Secondo SwiftLee (2025), il 40% dei bug di SwiftUI in produzione sono correlati a chiamate ripetute di onAppear.

Errore 2: perdita di memoria per riferimento forte. Se la closure di onAppear cattura self senza un riferimento debole, crea un ciclo di ritenzione con la View. SwiftUI non garantisce l’azzeramento degli oggetti catturati quando la View scompare. Usa la capture list [weak self] per ViewModel o servizi.

Errore 3: esecuzione su thread in background. onAppear viene eseguito sul thread principale — questo è corretto per le operazioni UI. Ma se avvii un Task all’interno di onAppear, assicurati che l’aggiornamento di @State avvenga tramite MainActor.run. Swift 5.9 e superiori tornano automaticamente a MainActor, ma è meglio specificare @MainActor esplicitamente.

Come evitare chiamate ripetute

Il pattern con un flag di caricamento è il modo più affidabile per proteggersi dalla duplicazione. Memorizza il flag in @State o @StateObject e reimpostalo solo all’aggiornamento manuale. Un’alternativa è usare .task invece di onAppear: .task non si riavvia al ridisegno per default se l’operazione async è già in esecuzione.

swift
struct SafeView: View {
    @State private var hasAppeared = false
    @State private var items: [Item] = []
    
    var body: some View {
        List(items, id: \.id) { item in
            Text(item.name)
        }
        .onAppear {
            guard !hasAppeared else { return }
            hasAppeared = true
            Task {
                items = await DataService.shared.fetchItems()
            }
        }
    }
}

Domande frequenti

In cosa .onAppear differisce da viewDidLoad in UIKit?

viewDidLoad viene chiamato una volta durante la vita di UIViewController, indipendentemente dalla visibilità. .onAppear viene chiamato ogni volta che una View viene aggiunta alla gerarchia — se una View viene rimossa e aggiunta di nuovo, onAppear si attiva nuovamente. In NavigationView, viewDidLoad viene chiamato durante l’inizializzazione, mentre onAppear viene chiamato a ogni visualizzazione dello schermo.

Si può chiamare una funzione async all’interno di .onAppear?

Sì, tramite un wrapper Task { await asyncFunction() }. Tuttavia, per le operazioni async è preferibile .task, che gestisce automaticamente l’annullamento e non richiede la creazione manuale di un Task. .task garantisce anche l’annullamento alla scomparsa della View, prevenendo perdite.

Perché .onAppear viene chiamato più volte?

La causa è la ricreazione del corpo della View a causa di modifiche a @State, @Published o alla configurazione di un antenato. SwiftUI può ridisegnare una View in risposta a modifiche in qualsiasi proprietà osservabile. Inoltre, LazyVStack e List chiamano onAppear per le celle che si avvicinano all’area visibile, e di nuovo quando si scorre verso l’alto.

.onAppear funziona su watchOS e tvOS?

Sì, .onAppear è disponibile su tutte le piattaforme SwiftUI: iOS 13+, watchOS 6+, tvOS 13+, macOS 10.15+. Il comportamento è identico: il modificatore viene chiamato quando una View viene aggiunta alla gerarchia. Su watchOS, onAppear si attiva quando l’app viene attivata dallo stato di standby, il che deve essere considerato nella progettazione.

Come passare parametri a .onAppear?

.onAppear non accetta parametri — solo una closure Void. Per passare parametri, usa una closure che cattura variabili esterne. Un approccio alternativo è creare un modificatore onAppear personalizzato con parametri tramite ViewModifier o un equivalente di .onChange.

Riepilogo

  • .onAppear è un modificatore SwiftUI per eseguire codice quando una View viene aggiunta alla gerarchia dell’interfaccia.
  • Chiamata singola — onAppear viene chiamato una volta per istanza di View se rimane in memoria.
  • Ordine genitore-primo — le View genitore ricevono onAppear prima dei figli.
  • Casi d’uso principali — caricamento dati, avvio animazioni, invio analisi.
  • .task è preferibile per operazioni async grazie all’annullamento automatico alla scomparsa della View.
  • Controllo di protezione — obbligatorio per evitare chiamate ripetute al ridisegno della View.

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