NavigationStack ist ein moderner Navigationscontainer in SwiftUI, der in iOS 16+ eingeführt wurde und NavigationView ersetzt. Laut Apple Developer Documentation, 2024 verwaltet NavigationStack einen Stapel von Bildschirmen über einen typsicheren Navigationspfad (NavigationPath), unterstützt tiefe Navigation, programmatische Rückkehr zum Startbildschirm und Zustandserhaltung bei Datenänderungen. Im Gegensatz zu NavigationView benötigt NavigationStack keine Umhüllung in einem zusätzlichen Container und bietet eine direkte Bindung an den Navigationspfad.
Wichtige Punkte
NavigationStack ist ein Container-View, der stapelbasierte Navigation (LIFO) implementiert. Es verwaltet den Verlauf der Übergänge, sodass Sie neue Bildschirme auf den Stapel legen und über die systemeigene „Zurück“-Schaltfläche oder programmatisch zurückkehren können. NavigationStack ist Teil von SwiftUI ab iOS 16, iPadOS 16, macOS 13, watchOS 9 und tvOS 16.
Die wichtigste Neuerung von NavigationStack ist der typsichere Navigationspfad. Anstatt beim Erstellen eines NavigationLink direkt ein Ziel anzugeben, legen Sie einen Wert in den Pfad, und das Ziel-View wird separat über den Modifikator .navigationDestination(for:destination:) registriert. Dies trennt Navigation von Darstellung und macht den Code modularer und testbarer.
Laut WWDC 2022 (Session 10054) verwendet NavigationStack einen neuen Navigationsmechanismus, der auf ObservableObject und dem SwiftUI-Lebenszyklus basiert. Im Gegensatz zu NavigationView, das intern auf UINavigationController angewiesen war, ist NavigationStack vollständig in SwiftUI implementiert, was die Vorhersagbarkeit und Kompatibilität mit dem SwiftUI-Lebenszyklus verbessert.
NavigationStack akzeptiert ein Wurzel-View und einen optionalen Navigationspfad (Binding an NavigationPath oder ein Array von Hashable-Werten). Alle untergeordneten Bildschirme werden über NavigationLink oder durch programmatisches Hinzufügen von Werten zum Pfad auf den Stapel gelegt.
NavigationView war der Hauptnavigationscontainer in SwiftUI vor iOS 16. Es verwaltete automatisch UINavigationController intern, was zu mehreren Problemen führte: unvorhersehbares Verhalten bei Datenänderungen, Komplexität bei programmatischer Navigation und fehlende Typsicherheit.
| Eigenschaft | NavigationStack (iOS 16+) | NavigationView (iOS 13–15) |
|---|---|---|
| Navigationstyp | Stapel (LIFO) | Stapel (LIFO) |
| Navigationspfad | Typisiert (NavigationPath) | Nicht unterstützt |
| Deep linking | Integrierte Unterstützung | Erfordert Workarounds |
| Programmatische Rückkehr | Über Pfad (pop, popToRoot) | dismiss, presentationMode |
| Intern | SwiftUI nativ | UINavigationController |
| Kompatibilität | iOS 16+ | iOS 13+ |
Hauptvorteil von NavigationStack — typsichere Navigation. Sie definieren den Pfad als Array spezifischer Typen (oder NavigationPath für heterogene Stapel) und registrieren ein Ziel für jeden Typ. Dadurch werden Typkonflikte vermieden und die Navigation wird vorhersagbar.
NavigationView ist in iOS 17 veraltet. Apple empfiehlt die Migration zu NavigationStack für alle neuen Projekte und bei der Aktualisierung der Mindestversion auf iOS 16.
NavigationPath ist ein Typ, der den Navigationspfad in NavigationStack darstellt. Er kann heterogene Werte (AnyHashable) speichern oder mit einem bestimmten Typ über Binding an ein Array [T: Hashable] verwendet werden. NavigationPath kodiert und dekodiert automatisch zur Zustandserhaltung.
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")
}
}
Heterogener Stapel: NavigationPath kann Werte verschiedener Typen enthalten, wenn sie Hashable implementieren. Beispielsweise kann der erste Bildschirm einen String (ID) akzeptieren, der zweite einen Int (Nummer), der dritte einen benutzerdefinierten enum Route. Jeder Typ registriert ein separates .navigationDestination zur Anzeige.
Codable-Unterstützung: NavigationPath implementiert Codable, wenn alle Werte im Pfad ebenfalls Codable + Hashable sind. Dies ermöglicht das Speichern und Wiederherstellen des Navigationszustands beim Neustart der App oder beim Wechsel in den Hintergrund.
.navigationDestination(for:destination:) — ein Modifikator, der ein Ziel-View für einen bestimmten Datentyp registriert. Wenn NavigationLink einen Wert dieses Typs in den Pfad legt, findet SwiftUI automatisch das entsprechende .navigationDestination und erstellt den Bildschirm.
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"))
Wichtige Regel: .navigationDestination muss auf ein View angewendet werden, das sich innerhalb von NavigationStack befindet, und bevor NavigationLink einen Wert in den Pfad legt. Es wird normalerweise zum Wurzel-View oder einem Abschnittscontainer hinzugefügt. Wenn für den Typ des Werts kein .navigationDestination gefunden wird, findet der Übergang nicht statt.
Laut SwiftUI Engineering (2023) kann .navigationDestination auf verschiedenen Ebenen der Hierarchie registriert werden. SwiftUI sucht während der Navigation nach dem nächstgelegenen passenden Ziel. Dies ermöglicht das Überschreiben des Ziels für einen Typ in verschiedenen Teilen der Anwendung.
Muster 1: Navigation über enum Route. Definieren Sie einen enum mit zugehörigen Werten für alle Bildschirme der Anwendung. Verwenden Sie ein .navigationDestination für AppRoute und einen switch für das Routing. Dies bietet eine einzige Quelle der Wahrheit für alle möglichen Übergänge in der Anwendung.
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)
}
Muster 2: Programmatische Navigation und Deep Linking. NavigationStack ermöglicht die programmatische Stapelverwaltung: Hinzufügen, Entfernen von Bildschirmen und Rückkehr zur Wurzel. Dies ist für Push-Benachrichtigungen, Deep Links und die Wiederherstellung der Navigation nach einem Neustart erforderlich.
Muster 3: Array von Typen statt NavigationPath. Wenn alle Bildschirme denselben Typ verwenden (z. B. String oder einen benutzerdefinierten enum), verwenden Sie Binding an [T]. Dies bietet eine stärkere Typisierung und bessere Leistung als NavigationPath. NavigationPath ist für heterogene Stapel mit unterschiedlichen Bildschirmtypen gerechtfertigt.
Laut Point-Free (2024) ist NavigationStack mit enum Route die bevorzugte Methode zur Organisation der Navigation in SwiftUI-Anwendungen. Es macht alle möglichen Übergänge explizit, typsicher und testbar, was besonders für große Projekte mit Dutzenden von Bildschirmen wichtig ist.
Häufig gestellte Fragen
NavigationStack — ein SwiftUI-Navigationscontainer (iOS 16+), der einen Stapel von Bildschirmen über einen typsicheren Pfad verwaltet. Er ersetzt NavigationView und bietet Unterstützung für Deep Linking, programmatische Navigation und Zustandserhaltung.
NavigationStack verwendet einen typsicheren Pfad (NavigationPath) anstatt NavigationLink direkt an ein Ziel zu binden. Es unterstützt programmatische Navigation, Deep Linking und Codable zur Zustandserhaltung. Es funktioniert auf SwiftUI, nicht über UINavigationController.
NavigationPath ist ein Typ, der eine Sequenz von Bildschirmen im Stapel darstellt. Sie fügen Werte zum Pfad über path.append() oder NavigationLink mit value hinzu. Jeder Typ registriert ein .navigationDestination zur Anzeige. NavigationPath unterstützt Codable und automatische Zustandserhaltung.
Über programmatische Pfadverwaltung: Nach der Verarbeitung der URL rufen Sie path.append() mit dem entsprechenden Routenwert auf. NavigationStack zeigt automatisch den Zielbildschirm an. Rückkehr zur Wurzel — path.removeLast(path.count).
Ja, wenn Ihre Mindestversion iOS 16+ ist. NavigationView ist in iOS 17 veraltet. Die Migration bietet typsichere Navigation, Deep-Linking-Unterstützung und bessere Übereinstimmung mit dem SwiftUI-Lebenszyklus. Für Projekte mit iOS 15 und niedriger verwenden Sie vorerst weiterhin NavigationView.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch