SwiftUI NavigationStack: Revolution of nested navigation with SwiftUI
If you are really struggling with multi level nested navigation with SwiftUIâs new NavigationStack and NavigationPath then this article is a huge plus point for you because I will discuss it deeply with a perfect sample project on GitHub
Lets jump into the coding with less talking đ. SwiftUIâs new navigation framework uses NavigationStack as a root view component and NavigationPath gives us such more powerful control over the whole navigation that was absent in the previous NavigationView component.
It is my suggestion that be patient and fully read the article, I can ensure you that you will not find any details description like this online. Surely 99% of your problems with new NavigationStack will be resolved.
At first we will see the normal nested navigation using NavigationStack and NavigationLink. Donât worry we will discuss the complex one later in this article. In the following ContentView.swift
file, if you click the NavigationLink it will show the first DetailsView.swift
. Since every NavigationStack has its own single stack, it will push the first DetailsView
onto that stack.
Then when you click the button in the DetailsView
to show the second DetailsView
another copy of DetailsView
will be pushed onto the first item of the NavigationStackâs stack. Similarly you can go clicking more and more into multiple nested DetailsView
as you wish. You will look that here I used one single DetailsView.swift
file for simplicity but you can use different files. Look at the following output:
Now the complex (not too muchđ) part of NavigationStack is using NavigationPath we can handle the navigation of NavigationStack. For example I want to go back to the first DetailView
from the fourth DetailsView
skipping all the middle views. In this case NavigationPath shows itâs ⨠magic ⨠. We can store any Hashable
data in NavigationPath and for every data type we have to set a navigationDestination
using the function navigationDestination(for: )
so that every time we push a data onto the NavigationPath stack and NavigationStack navigate the View
to the corresponding destination details view with that data.
This is called the new data driven navigation approach initiated by SwiftUI
See the following ContentView.swift
file. There are two types of data named FastFood
and Cloth
. We set details destination for both data but we also defined another destination for data type String
because we will navigate into two different list View
dynamically depending on the Tag
of those Views
. See FoodItemListView.tag
directs to FoodItemListView
and ClothItemListView.tag
directs us to ClothItemListView
.
Very important !!! Remember when you are using NavigationPath with NavigationStack, each navigation from first
View
should be done with NavigationPath. Donât do any navigation without NavigationPath. Otherwise aView
that was navigated to without NavigationPath can become appear again and again like a loop!!!
Did you notice that in the first case we did not use any NavigationLink? Only pushing data to the NavigationPath like: path.append(FoodItemListView.tag)
directs us to the corresponding destinations đ.
In the second case we used NavigationLink like NavigationLink(value: ClothItemListView.tag)
, so you can push any data to the NavigationLink and the data will be automatically pushed or appended to the NavigationPath by NavigationLink and your View
will be directed to the corresponding destination View
by NavigationStack according to your declaration of navigationDestination(for: )
function.
Every FoodItemDetailsView
and ClothItemDetailsView
contains related foods and cloths. You can go further more details views clicking those food and cloth items. Now if you want to go back to the first list view skipping all middle details views, how can you do that? Just remove all corresponding data for those middle views from the path stack keeping only the first one, NavigationStack will automatically direct you to the first View
. Similarly you can go back to the second, third whatever View
you want like below:
Button(action: {
while path.count > 1 { // For going back to the first view đ
path.removeLast()
}
})
Button(action: {
while path.count > 3 { // For going back to the third view đ
path.removeLast()
}
})
Now see the output:
So, thatâs it for today đ you can download the full sample little project from this GitHub link. If you find anything wrong or if you have any questions just comment below, I will try to answer as soon as possible. Donât forget to clap it and star the sample project đĽ°