Formation PUB900 : Développer une application pour iPhone avec SwiftUI, H-2024 Les applications multivues

40.1 NavigationLink et .navigationDestination()


Il existe différentes techniques pour changer de page – ou plus précisément de vue – en SwiftUI.

Dans cette fiche :

Lien vers une autre vue avec NavigationLink(destination:...)

À 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.

SwiftUI

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.

NavigationLink    NavigationLink

Notez bien que si vous ajoutez un NavigationLink en dehors d'un NavigationStack, il ne sera pas cliquable donc il sera inutile.

List

Lorsque le NavigationLink est utilisé à l'intérieur d'un List, son apparence est automatiquement adaptée au style standard d'iOS.

SwiftUI

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

NavigationLink dans List

Vue personnalisée

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.

SwiftUI

NavigationStack {
  VStack() {
    ...
  }
  .toolbar(content: {
    ToolbarItem(placement: .navigationBarTrailing, content: {
      NavigationLink(destination: AjouterItem()) {
        Image(systemName: "plus.circle")
      }
    })
  })
}

Fichier Views/VueAjouterItem.swift

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.

Fichier Views/ContentView.swift

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.

Fichier Views/ListeItems.swift

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

  }

}

Lien vers une autre vue avec Button et .navigationDestination(isPresented:)

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.

SwiftUI

@State private var afficherAutrePage = false
...
VStack {
  Button(action: {
    afficherAutrePage = true
  }) {
    Text("Autre page")
  }
}
.navigationDestination(isPresented: $afficherAutreVue) {
   AutreVue()
}

Lien vers une autre vue avec Button et .navigationDestination(item:)

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é.

SwiftUI

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.

SwiftUI

struct DetailItem: View {
  var item: Item

  var body: some View {
    Text("Item généré : \(item.titre)")
      .navigationTitle("Détail")
  }
}

Pour plus d'information

« Better Navigation in SwiftUI with NavigationStack ». Swifty Place. https://www.swiftyplace.com/blog/better-navigation-in-swiftui-with-navigation-stack

▼Publicité

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Merci de partager !
Soumettre