NavigationStack: cos'è, pila di navigazione in SwiftUI

Autore: IT Sectr Pubblicato: 2026-06-24 Tempo di lettura: 6 min

NavigationStack è un contenitore di navigazione moderno in SwiftUI, introdotto in iOS 16+ e che sostituisce NavigationView. Secondo la Documentazione per sviluppatori Apple, 2024, NavigationStack gestisce una pila di schermi attraverso un percorso di navigazione type-safe (NavigationPath), supporta la navigazione profonda, il ritorno programmatico allo schermo principale e la preservazione dello stato quando i dati cambiano. A differenza di NavigationView, NavigationStack non richiede l'incapsulamento in un contenitore aggiuntivo e fornisce un Binding diretto al percorso di navigazione.

Punti chiave

  • NavigationStack — nuovo contenitore di navigazione SwiftUI (iOS 16+)
  • NavigationPath — percorso type-safe per gestire la pila di schermi
  • Deep linking — supporto per navigazione programmatica tramite percorso
  • NavigationDestination — registrazione degli schermi di destinazione per tipi di dati
  • Lo stato di navigazione viene preservato e ripristinato automaticamente

Cos'è NavigationStack in SwiftUI?

NavigationStack è una vista contenitore che implementa la navigazione basata su pila (LIFO). Gestisce la cronologia delle transizioni, consentendo di inserire nuovi schermi nella pila e tornare indietro tramite il pulsante “Indietro” di sistema o programmaticamente. NavigationStack fa parte di SwiftUI a partire da iOS 16, iPadOS 16, macOS 13, watchOS 9 e tvOS 16.

La principale innovazione di NavigationStack è il percorso di navigazione type-safe. Invece di specificare direttamente una destinazione quando si crea un NavigationLink, si inserisce un valore nel percorso e la vista di destinazione viene registrata separatamente tramite il modificatore .navigationDestination(for:destination:). Questo separa la navigazione dal rendering, rendendo il codice più modulare e testabile.

Secondo WWDC 2022 (Sessione 10054), NavigationStack utilizza un nuovo meccanismo di navigazione basato su ObservableObject e il ciclo di vita di SwiftUI. A differenza di NavigationView, che si affidava internamente a UINavigationController, NavigationStack è completamente implementato in SwiftUI, migliorando la prevedibilità e la compatibilità con il ciclo di vita di SwiftUI.

Struttura base di NavigationStack

NavigationStack accetta una vista radice e un percorso di navigazione opzionale (Binding a NavigationPath o un array di valori Hashable). Tutti gli schermi figli vengono inseriti nella pila tramite NavigationLink o aggiungendo valori programmaticamente al percorso.

NavigationView era il contenitore di navigazione principale in SwiftUI prima di iOS 16. Gestiva automaticamente UINavigationController internamente, il che portava a diversi problemi: comportamento imprevedibile quando i dati cambiavano, complessità con la navigazione programmatica e mancanza di type safety.

CaratteristicaNavigationStack (iOS 16+)NavigationView (iOS 13–15)
Tipo di navigazionePila (LIFO)Pila (LIFO)
Percorso di navigazioneTipizzato (NavigationPath)Non supportato
Deep linkingSupporto integratoRichiede soluzioni
Ritorno programmaticoTramite percorso (pop, popToRoot)dismiss, presentationMode
InternamenteSwiftUI nativoUINavigationController
CompatibilitàiOS 16+iOS 13+

Vantaggio chiave di NavigationStack — navigazione type-safe. Si definisce il percorso come un array di tipi specifici (o NavigationPath per pile eterogenee) e si registra una destinazione per ogni tipo. Questo elimina gli errori di disallineamento dei tipi e rende la navigazione prevedibile.

NavigationView è deprecato in iOS 17. Apple raccomanda di migrare a NavigationStack per tutti i nuovi progetti e quando si aggiorna la versione minima a iOS 16.

NavigationPath è un tipo che rappresenta il percorso di navigazione in NavigationStack. Può memorizzare valori eterogenei (AnyHashable) o essere utilizzato con un tipo specifico tramite Binding a un array [T: Hashable]. NavigationPath codifica e decodifica automaticamente per la preservazione dello stato.

swift
struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            HomeView()
                .navigationDestination(for: String.self) { value in
                    DetailView(id: value)
                }
                .navigationDestination(for: Int.self) { value in
                    NumberView(number: value)
                }
        }
    }

    func goToRoot() {
        path.removeLast(path.count)
    }

    func pushDeepLink() {
        path.append("detail_42")
    }
}

Pila eterogenea: NavigationPath può contenere valori di diversi tipi se implementano Hashable. Ad esempio, il primo schermo può accettare un String (ID), il secondo un Int (numero), il terzo un enum Route personalizzato. Ogni tipo registra un .navigationDestination separato per la visualizzazione.

Supporto Codable: NavigationPath implementa Codable se tutti i valori nel percorso sono anche Codable + Hashable. Questo consente di salvare e ripristinare lo stato di navigazione quando si riavvia l'app o si passa in background.

.navigationDestination(for:destination:) — un modificatore che registra una vista di destinazione per un tipo di dati specifico. Quando NavigationLink inserisce un valore di questo tipo nel percorso, SwiftUI trova automaticamente il .navigationDestination corrispondente e crea lo schermo.

swift
enum AppRoute: Hashable {
    case profile(UserID)
    case settings
    case about
}

struct AppNavigation: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            HomeView()
                .navigationDestination(for: AppRoute.self) { route in
                    switch route {
                    case .profile(let id):
                        ProfileView(userId: id)
                    case .settings:
                        SettingsView()
                    case .about:
                        AboutView()
                    }
                }
        }
    }
}

// Navigate: path.append(AppRoute.profile("user_123"))

Regola importante: .navigationDestination deve essere applicato a una vista che si trova all'interno di NavigationStack e prima che NavigationLink inserisca un valore nel percorso. Di solito viene aggiunto alla vista radice o a un contenitore di sezione. Se non viene trovato alcun .navigationDestination per il tipo del valore, la transizione non avverrà.

Secondo SwiftUI Engineering (2023), .navigationDestination può essere registrato a diversi livelli della gerarchia. SwiftUI cerca la destinazione corrispondente più vicina durante la navigazione. Ciò consente di sovrascrivere la destinazione per un tipo in diverse parti dell'applicazione.

Pattern 1: navigazione tramite enum Route. Definite un enum con valori associati per tutti gli schermi dell'applicazione. Usate un .navigationDestination per AppRoute e uno switch per il routing. Questo fornisce un'unica fonte di verità per tutte le possibili transizioni nell'applicazione.

swift
struct StoreView: View {
    @State private var path: [ProductRoute] = []

    var body: some View {
        NavigationStack(path: $path) {
            ProductGrid()
                .navigationDestination(for: ProductRoute.self) { route in
                    switch route {
                    case .detail(let product):
                        ProductDetail(product: product)
                    case .reviews(let productId):
                        ReviewsView(productId: productId)
                    }
                }
        }
    }
}

enum ProductRoute: Hashable {
    case detail(Product)
    case reviews(String)
}

Pattern 2: navigazione programmatica e deep linking. NavigationStack consente la gestione programmatica della pila: aggiunta, rimozione di schermi e ritorno alla radice. Ciò è necessario per notifiche push, deep link e ripristino della navigazione dopo un riavvio.

Pattern 3: array di tipi invece di NavigationPath. Se tutti gli schermi utilizzano lo stesso tipo (ad esempio, String o un enum personalizzato), usate Binding a [T]. Questo offre una tipizzazione più forte e prestazioni migliori rispetto a NavigationPath. NavigationPath è giustificato per pile eterogenee con diversi tipi di schermo.

Secondo Point-Free (2024), NavigationStack con enum Route è il modo preferito per organizzare la navigazione nelle applicazioni SwiftUI. Rende tutte le possibili transizioni esplicite, type-safe e testabili, il che è particolarmente importante per grandi progetti con decine di schermi.

Domande frequenti

Cos'è NavigationStack in SwiftUI?

NavigationStack — un contenitore di navigazione SwiftUI (iOS 16+) che gestisce una pila di schermi tramite un percorso type-safe. Ha sostituito NavigationView, offrendo supporto per deep linking, navigazione programmatica e preservazione dello stato.

In cosa si differenzia NavigationStack da NavigationView?

NavigationStack utilizza un percorso type-safe (NavigationPath) invece di legare direttamente NavigationLink a una destinazione. Supporta la navigazione programmatica, il deep linking e Codable per la preservazione dello stato. Funziona su SwiftUI, non tramite UINavigationController.

Come funziona NavigationPath?

NavigationPath è un tipo che rappresenta una sequenza di schermi nella pila. Si aggiungono valori al percorso tramite path.append() o NavigationLink con value. Ogni tipo registra un .navigationDestination per la visualizzazione. NavigationPath supporta Codable e la preservazione automatica dello stato.

Come implementare il deep linking con NavigationStack?

Attraverso la gestione programmatica del percorso: dopo aver elaborato l'URL, chiamate path.append() con il valore di route corrispondente. NavigationStack visualizza automaticamente lo schermo di destinazione. Ritorno alla radice — path.removeLast(path.count).

Devo migrare da NavigationView a NavigationStack?

Sì, se la vostra versione minima è iOS 16+. NavigationView è deprecato in iOS 17. La migrazione fornisce navigazione type-safe, supporto per deep linking e un migliore allineamento con il ciclo di vita di SwiftUI. Per progetti con iOS 15 e versioni precedenti, continuate a usare NavigationView per ora.

Riepilogo

  • NavigationStack — contenitore di navigazione SwiftUI moderno (iOS 16+)
  • NavigationPath — percorso type-safe per gestire la pila di schermi
  • NavigationDestination — registrazione di viste di destinazione per tipi di dati
  • NavigationView deprecato in iOS 17, migrazione raccomandata
  • Deep linking e navigazione programmatica — supporto integrato
  • Enum Route — pattern preferito per organizzare la navigazione
  • Pila eterogenea tramite NavigationPath con qualsiasi tipo Hashable

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