NavigationStack and NavigationPath in SwiftUI
1️⃣ What is NavigationStack?
NavigationStack and NavigationPath in SwiftUI
1️⃣ What is NavigationStack?
👉 Definition
NavigationStack is the modern SwiftUI navigation container (iOS 16+).
It replaces NavigationView and manages a stack-based navigation flow.
📦 Think of it like a stack of screens:
- Push → add a screen on top
- Pop → remove the top screen
✅ Basic Example
NavigationStack {
Text("Home Screen")
.navigationTitle("Home")
}
2️⃣ What is NavigationPath?
👉 Definition
NavigationPath is a data model that represents the entire navigation history of a NavigationStack.
Instead of navigation being driven by views, it’s driven by data.
🧠 Mental Model
NavigationPath = [Screen1, Screen2, Screen3]
If you modify the array → navigation updates automatically.
✅ Simple Example
@State private var path = NavigationPath()
NavigationStack(path: $path) {
Button("Go to Details") {
path.append("details")
}
}
3️⃣ Navigation without NavigationPath (Simple case)
Use this when navigation is static and linear.
NavigationStack {
NavigationLink("Go to Details", value: "details")
.navigationDestination(for: String.self) { value in
Text("Details Screen")
}
}
✔ Good for:
- Simple apps
- Few screens
- No deep linking
4️⃣ Navigation WITH NavigationPath (Recommended)
Use this when navigation is dynamic, programmatic, or deep-linked.
🧩 Full Example (Best Practice)
enum Screen: Hashable {
case home
case details
case profile
}
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack(spacing: 20) {
Button("Go to Details") {
path.append(Screen.details)
}
Button("Go to Profile") {
path.append(Screen.profile)
}
}
.navigationTitle("Home")
.navigationDestination(for: Screen.self) { screen in
switch screen {
case .details:
Text("Details Screen")
case .profile:
Text("Profile Screen")
case .home:
Text("Home Screen")
}
}
}
}
}
📌 Final Cheat Sheet
NavigationStack // Container
NavigationPath // State
navigationDestination // Screen resolver
path.append() // Push
path.removeLast() // Pop
path = NavigationPath() // Reset
Example: NavigationPath in Action (Details Explanation)
Step 1: Enum for Routes
Define multiple destinations for the navigation stack with an enum. Each case can carry different types of associated data.
// Define your screens
enum Route: Hashable {
case view1. // No associated data
case view2(id: Int) // Int type
case view3(String) // Associated value for data passing
}
Step 2: Use NavigationPath
The NavigationPath will type-erase the list of Route values you push into it.
Create router Class (ObservableObject): This class manages the navigation logic:
import SwiftUI
class Router: ObservableObject {
@Published var path = NavigationPath()
func pushView(_ route: Route) {
path.append(route)
}
func popToRoot() {
path = NavigationPath() // Clears the stack
}
func popToSpecificView(count: Int) {
path.removeLast(count) // Removes `count` views from the stack
}
}
Step 2: Create Views
Each view interacts with the Router object.
// View 1
// Define your screens
struct View1: View {
@EnvironmentObject var router: Router
var body: some View {
VStack {
Text("View 1")
Button("Go to View 2") {
router.pushView(.view2)
}
}
}
}
//***************************************************
// View 2
struct View2: View {
@EnvironmentObject var router: Router
var body: some View {
VStack {
Text("View 2")
Button("Go to View 3") {
router.pushView(.view3("Niraj Paul")) // Passing data
}
}
}
}
//***************************************************
// View 3
struct View3: View {
@EnvironmentObject var router: Router
var name: String
var body: some View {
VStack {
Text("Hello, \(name)")
Button("Go to Root") {
router.popToRoot() // Pop to root view
}
Button("Go to View 1") {
router.popToSpecificView(count: 2) // Go back two views
}
}
}
}
Step 3: NavigationStack Container
This container links the router to the views and manages navigation.
struct AppContainerView: View {
@StateObject var router = Router()
var body: some View {
NavigationStack(path: $router.path) {
View1()
.navigationDestination(for: Route.self) { route in
switch route {
case .view1:
View1()
case .view2:
View2()
case .view3(let name):
View3(name: name)
}
}
}
.environmentObject(router) // Provide Router to all views
}
}
Thank you
Niraj Paul
메타데이터
- post_id
- 33a5c7a51eaa
- slug
- navigationstack-and-navigationpath-in-swiftui-33a5c7a51eaa
- url
- https://medium.com/@nirajpaul2/navigationstack-and-navigationpath-in-swiftui-33a5c7a51eaa
- canonical_url
- https://medium.com/@nirajpaul2/navigationstack-and-navigationpath-in-swiftui-33a5c7a51eaa
- author_url
- https://medium.com/@nirajpaul2
- status
- ok
- fetched_at
- 2026-08-27 20:45:58