Il existe différentes techniques pour changer de page – ou plus précisément de vue – en SwiftUI.
Dans cette fiche :
À l'intérieur d'un NavigationStack, il est possible d'ajouter des vues de type NavigationLink.
Un NavigationLink est un lien qui mène à une autre vue.
Dans sa forme la plus simple, le lien de navigation affiche une vue qui affiche le texte spécifié.
Dans la vue affichée par le lien, SwiftUI ajoute automatiquement un bouton de retour dans la barre de navigation pour revenir à la vue précédente.
var body: some View {
NavigationStack {
VStack {
NavigationLink(destination: Text("Vous êtes à la page 1")) {
Text("Aller à la page 1")
}
.padding()
NavigationLink(destination: Text("Vous êtes à la page 2")) {
Text("Aller à la page 2")
}
.padding()
NavigationLink(destination: Text("Vous êtes à la page 3")) {
Text("Aller à la page 3")
}
.padding()
}
.navigationTitle("Mon application")
}
}
Remarquez le bouton de retour dans la vue enfant. Il présente un simple chevron (<). Avant iOS 26, sorti en 2025, il affichait un chevron suivi du titre de la page d'avant.

Notez bien que si vous ajoutez un NavigationLink en dehors d'un NavigationStack, il ne sera pas cliquable donc il sera inutile.
Lorsque le NavigationLink est utilisé à l'intérieur d'un List, son apparence est automatiquement adaptée au style standard d'iOS.
var body: some View {
NavigationStack {
List {
NavigationLink(destination: Text("Vous êtes à la page 1")) {
Text("Aller à la page 1")
}
.padding()
NavigationLink(destination: Text("Vous êtes à la page 2")) {
Text("Aller à la page 2")
}
.padding()
NavigationLink(destination: Text("Vous êtes à la page 3")) {
Text("Aller à la page 3")
}
.padding()
}
.navigationTitle("Mon application")
.navigationBarTitleDisplayMode(.inline)
}
}

Toute la puissance de NavigationLink apparaît lorsqu'il mène vers une vue plus complexe plutôt qu'un simple texte.
Il suffit de créer une vue SwiftUI dans un nouveau fichier, d'y définir son contenu, puis d'y faire référence dans le NavigationLink.
Notez que par convention, on placera toutes les vues dans un dossier nommé Views. Ce dossier sera placé à la racine de l'application, au même niveau que Assets.xcassets.
Cet extrait de code permet d'afficher une page d'ajout en cliquant sur une icône dans la barre de navigation.
NavigationStack {
VStack() {
...
}
.toolbar(content: {
ToolbarItem(placement: .navigationBarTrailing, content: {
NavigationLink(destination: AjouterItem()) {
Image(systemName: "plus.circle")
}
})
})
}
import SwiftUI
struct AjouterItem: View {
var body: some View {
// Remarquez qu'il ne faut pas ajouter un nouveau NavigationStack dans la vue
VStack {
...
}
.navigationTitle("Ajouter un item")
}
}
NavigationLink peut aussi utiliser une syntaxe différente qui permet de centraliser la navigation.
On lui passera en paramètre un value et c'est le .navigationDestination(for:) qui se chargera de passer cette valeur à la vue enfant.
Ceci est souvent utilisé dans une liste d'instances quand on doit passer l'instance courante en paramètre à la vue enfant.
struct ContentView: View {
@Query(sort: \Categorie.titre) var categories: [Categorie]
var body: some View {
NavigationStack {
List (categories) { categorie in
NavigationLink(value: categorie) {
Text(categorie.titre)
}
}
.navigationDestination(for: Categorie.self) { categorie in
ListeItems(categorie: categorie)
}
.navigationTitle("Mon application")
}
}
}
Et dans la vue enfant, la catégorie sera reçue en paramètre.
struct ListeItems: View {
var categorie: Categorie
var body: some View {
if let items = categorie.items, !items.isEmpty {
ForEach(items.sorted(by: {$0.code < $1.code})) { item in
Text("\(item.code) - \(item.titre)")
}
}
else {
Text("Il n'y a aucun item dans la catégorie \(categorie.titre).")
}
}
}
Un bouton est lui aussi capable d'afficher une autre vue. L'astuce consiste à lui faire modifier la valeur d'une variable d'état et à naviguer vers la destination seulement si la variable d'état est à true.
Ceci est possible grâce à .navigationDestination(isPresented:), qui attend une valeur booléenne pour savoir si la vue doit être affichée ou non.
@State private var afficherAutrePage = false
...
VStack {
Button(action: {
afficherAutrePage = true
}) {
Text("Autre page")
}
}
.navigationDestination(isPresented: $afficherAutreVue) {
AutreVue()
}
Si le bouton doit mener vers une vue de destination qui attend des données en paramètre, il faut se tourner vers .navigationDestination(item:).
La vue enfant sera affichée dès que le paramètre passé à .navigationDestination(item:) n'a plus la valeur nil.
Contrairement à .navigationDestination(for:), cette approche est particulièrement utile lorsque la navigation dépend d’un résultat calculé ou généré dynamiquement, plutôt que d’un élément affiché dans une liste.
Dans l’exemple suivant, l’utilisateur clique sur un bouton pour générer un item aléatoire, puis navigue automatiquement vers la fiche de l'item généré.
struct ContentView: View {
@State private var itemGenere: Item? = nil
let titres = ["Clavier", "Souris", "Écran", "Imprimante"]
var body: some View {
NavigationStack {
VStack(spacing: 20) {
Button("Générer un item au hasard") {
let titreAleatoire = titres.randomElement()!
itemGenere = Item(titre: titreAleatoire)
}
}
.navigationTitle("Générateur")
.navigationDestination(item: $itemGenere) { item in // $ pour que la valeur soit remise à nil quand on referme la vue enfant
DetailItem(item: item)
}
}
}
}
La vue affichée recevra l'item en paramètre.
struct DetailItem: View {
var item: Item
var body: some View {
Text("Item généré : \(item.titre)")
.navigationTitle("Détail")
}
}
« Better Navigation in SwiftUI with NavigationStack ». Swifty Place. https://www.swiftyplace.com/blog/better-navigation-in-swiftui-with-navigation-stack
▼Publicité