NavigationStack : qu'est-ce que c'est, pile de navigation dans SwiftUI

Auteur : IT Sectr Publié le : 2026-06-24 Temps de lecture : 6 min

NavigationStack est un conteneur de navigation moderne dans SwiftUI, introduit dans iOS 16+ et remplaçant NavigationView. Selon la Documentation Apple Developer, 2024, NavigationStack gère une pile d'écrans via un chemin de navigation typé (NavigationPath), prend en charge la navigation profonde, le retour programmatique à l'écran racine et la préservation de l'état lors des modifications de données. Contrairement à NavigationView, NavigationStack ne nécessite pas d'encapsulation dans un conteneur supplémentaire et fournit une liaison directe au chemin de navigation.

Points clés

  • NavigationStack — nouveau conteneur de navigation SwiftUI (iOS 16+)
  • NavigationPath — chemin typé pour gérer la pile d'écrans
  • Deep linking — prise en charge de la navigation programmatique via le chemin
  • NavigationDestination — enregistrement des écrans de destination par types de données
  • L'état de navigation est préservé et restauré automatiquement

Qu'est-ce que NavigationStack dans SwiftUI ?

NavigationStack est une vue conteneur qui implémente la navigation basée sur une pile (LIFO). Elle gère l'historique des transitions, vous permettant de pousser de nouveaux écrans sur la pile et de revenir en arrière via le bouton « Précédent » du système ou par programmation. NavigationStack fait partie de SwiftUI depuis iOS 16, iPadOS 16, macOS 13, watchOS 9 et tvOS 16.

La principale innovation de NavigationStack est le chemin de navigation typé. Au lieu de spécifier directement une destination lors de la création d'un NavigationLink, vous placez une valeur dans le chemin, et la vue de destination est enregistrée séparément via le modificateur .navigationDestination(for:destination:). Cela sépare la navigation du rendu, rendant le code plus modulaire et testable.

Selon la WWDC 2022 (Session 10054), NavigationStack utilise un nouveau mécanisme de navigation basé sur ObservableObject et le cycle de vie de SwiftUI. Contrairement à NavigationView qui reposait sur UINavigationController en interne, NavigationStack est entièrement implémenté en SwiftUI, améliorant la prévisibilité et la compatibilité avec le cycle de vie de SwiftUI.

Structure de base de NavigationStack

NavigationStack accepte une vue racine et un chemin de navigation optionnel (Binding à NavigationPath ou un tableau de valeurs Hashable). Tous les écrans enfants sont poussés sur la pile via NavigationLink ou en ajoutant programmatiquement des valeurs au chemin.

NavigationView était le principal conteneur de navigation dans SwiftUI avant iOS 16. Il gérait automatiquement UINavigationController en interne, ce qui entraînait plusieurs problèmes : comportement imprévisible lors des modifications de données, complexité de la navigation programmatique et absence de typage fort.

CaractéristiqueNavigationStack (iOS 16+)NavigationView (iOS 13–15)
Type de navigationPile (LIFO)Pile (LIFO)
Chemin de navigationTypé (NavigationPath)Non supporté
Deep linkingSupport intégréNécessite des solutions
Retour programmatiqueVia le chemin (pop, popToRoot)dismiss, presentationMode
Sous le capotSwiftUI natifUINavigationController
CompatibilitéiOS 16+iOS 13+

Avantage clé de NavigationStack — la navigation typée. Vous définissez le chemin comme un tableau de types spécifiques (ou NavigationPath pour les piles hétérogènes) et enregistrez une destination pour chaque type. Cela élimine les erreurs d'incompatibilité de types et rend la navigation prévisible.

NavigationView est déprécié dans iOS 17. Apple recommande de migrer vers NavigationStack pour tous les nouveaux projets et lors de la mise à jour de la version minimale vers iOS 16.

NavigationPath est un type représentant le chemin de navigation dans NavigationStack. Il peut stocker des valeurs hétérogènes (AnyHashable) ou être utilisé avec un type spécifique via Binding à un tableau [T: Hashable]. NavigationPath s'encode et se décode automatiquement pour la préservation de l'état.

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

Pile hétérogène : NavigationPath peut contenir des valeurs de différents types s'ils implémentent Hashable. Par exemple, le premier écran peut accepter un String (ID), le second un Int (nombre), le troisième un enum Route personnalisé. Chaque type enregistre un .navigationDestination séparé pour l'affichage.

Support Codable : NavigationPath implémente Codable si toutes les valeurs du chemin sont également Codable + Hashable. Cela permet de sauvegarder et de restaurer l'état de navigation lors du redémarrage de l'application ou du passage en arrière-plan.

.navigationDestination(for:destination:) — un modificateur qui enregistre une vue de destination pour un type de données spécifique. Lorsque NavigationLink place une valeur de ce type dans le chemin, SwiftUI trouve automatiquement le .navigationDestination correspondant et crée l'écran.

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

Règle importante : .navigationDestination doit être appliqué à une vue qui se trouve à l'intérieur de NavigationStack, et avant que NavigationLink ne place une valeur dans le chemin. Il est généralement ajouté à la vue racine ou à un conteneur de section. Si aucun .navigationDestination n'est trouvé pour le type de la valeur, la transition n'aura pas lieu.

Selon SwiftUI Engineering (2023), .navigationDestination peut être enregistré à différents niveaux de la hiérarchie. SwiftUI recherche la destination correspondante la plus proche lors de la navigation. Cela permet de remplacer la destination pour un type dans différentes parties de l'application.

Patron 1 : navigation via enum Route. Définissez un enum avec des valeurs associées pour tous les écrans de l'application. Utilisez un .navigationDestination pour AppRoute et un switch pour le routage. Cela fournit une source unique de vérité pour toutes les transitions possibles dans l'application.

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

Patron 2 : navigation programmatique et deep linking. NavigationStack permet la gestion programmatique de la pile : ajout, suppression d'écrans et retour à la racine. Cela est nécessaire pour les notifications push, les deep links et la restauration de la navigation après un redémarrage.

Patron 3 : tableau de types au lieu de NavigationPath. Si tous les écrans utilisent le même type (par exemple, String ou un enum personnalisé), utilisez Binding à [T]. Cela offre un typage plus fort et de meilleures performances que NavigationPath. NavigationPath est justifié pour les piles hétérogènes avec différents types d'écrans.

Selon Point-Free (2024), NavigationStack avec enum Route est la manière préférée d'organiser la navigation dans les applications SwiftUI. Il rend toutes les transitions possibles explicites, typées et testables, ce qui est particulièrement important pour les grands projets avec des dizaines d'écrans.

Foire aux questions

Qu'est-ce que NavigationStack dans SwiftUI ?

NavigationStack — un conteneur de navigation SwiftUI (iOS 16+) qui gère une pile d'écrans via un chemin typé. Il a remplacé NavigationView, offrant un support pour le deep linking, la navigation programmatique et la préservation de l'état.

En quoi NavigationStack diffère-t-il de NavigationView ?

NavigationStack utilise un chemin typé (NavigationPath) au lieu de lier directement NavigationLink à une destination. Il prend en charge la navigation programmatique, le deep linking et Codable pour la préservation de l'état. Il fonctionne sur SwiftUI, pas via UINavigationController.

Comment fonctionne NavigationPath ?

NavigationPath est un type représentant une séquence d'écrans dans la pile. Vous ajoutez des valeurs au chemin via path.append() ou NavigationLink avec value. Chaque type enregistre un .navigationDestination pour l'affichage. NavigationPath prend en charge Codable et la préservation automatique de l'état.

Comment implémenter le deep linking avec NavigationStack ?

Grâce à la gestion programmatique du chemin : après avoir traité l'URL, appelez path.append() avec la valeur de route correspondante. NavigationStack affiche automatiquement l'écran cible. Retour à la racine — path.removeLast(path.count).

Dois-je migrer de NavigationView vers NavigationStack ?

Oui, si votre version minimale est iOS 16+. NavigationView est déprécié dans iOS 17. La migration offre une navigation typée, un support du deep linking et un meilleur alignement avec le cycle de vie de SwiftUI. Pour les projets ciblant iOS 15 et inférieur, continuez à utiliser NavigationView pour l'instant.

Résumé

  • NavigationStack — conteneur de navigation SwiftUI moderne (iOS 16+)
  • NavigationPath — chemin typé pour gérer la pile d'écrans
  • NavigationDestination — enregistrement des vues de destination par types de données
  • NavigationView déprécié dans iOS 17, migration recommandée
  • Deep linking et navigation programmatique — support intégré
  • Enum Route — patron préféré pour organiser la navigation
  • Pile hétérogène via NavigationPath avec tout type Hashable

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi