In iOS growth, navigation view is unquestionably one of the generally used elements. When SwiftUI was first launched, it got here with a view referred to as NavigationView
for builders to construct navigation-based consumer interfaces. With the discharge of iOS 16, Apple has deprecated the previous navigation view and launched a brand new view generally known as NavigationStack
to current a stack of views. Most significantly, builders could make use of this new view to construct knowledge pushed navigation.
The Previous Means of Navigation Views
Previous to iOS 16, you create a navigation interface utilizing NavigationView
and NavigationLink
like this:
NavigationView { Â Â Â Â NavigationLink { Â Â Â Â Â Â Â Â Textual content(“Vacation spot”) Â Â Â Â } label: { Â Â Â Â Â Â Â Â Textual content(“Faucet me”) Â Â Â Â } } |
This creates a primary navigation based mostly interface with a Faucet me button. When tapped, the app navigates one stage right down to show the vacation spot view.
Working with NavigationStack
Ranging from iOS 16, you change NavigationView
with the brand new NavigationStack
. You may preserve the NavigationLink
intact and obtain the identical consequence.
NavigationStack { Â Â Â Â NavigationLink { Â Â Â Â Â Â Â Â Textual content(“Vacation spot”) Â Â Â Â } label: { Â Â Â Â Â Â Â Â Textual content(“Faucet me”) Â Â Â Â } } |
The identical piece of the code may also be written like this:
NavigationStack { Â Â Â Â NavigationLink(“Faucet me”) { Â Â Â Â Â Â Â Â Textual content(“Vacation spot”) Â Â Â Â } } |
We often use navigation views to construct a master-detail movement for a listing of knowledge gadgets. Right here is an instance:
var physique: some View {
NavigationStack {
Listing(bgColors, id: .self) { bgColor in
NavigationLink {
bgColor
.body(maxWidth: .infinity, maxHeight: .infinity)
} label: {
Textual content(bgColor.description)
}
}
.listStyle(.plain)
.navigationTitle(“Shade”)
}
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
struct ContentView: View {     non-public var bgColors: [Color] = [ .indigo, .yellow, .green, .orange, .brown ]      var physique: some View {          NavigationStack {             Listing(bgColors, id: .self) { bgColor in                 NavigationLink {                     bgColor                         .body(maxWidth: .infinity, maxHeight: .infinity)                 } label: {                     Textual content(bgColor.description)                 }              }             .listStyle(.plain)              .navigationTitle(“Shade”)         }      } } |
This creates a navigation view to show a listing of colour gadgets. When an merchandise is chosen, the app navigates to the element view and exhibits the colour view.
Worth-based Navigation Hyperlinks
NavigationStack
introduces a brand new modifier referred to as navigationDestination
that associates a vacation spot view with a offered knowledge kind. The identical piece of code within the earlier part may be rewritten like this:
NavigationLink(worth: bgColor) {
Textual content(bgColor.description)
}
}
.listStyle(.plain)
.navigationDestination(for: Shade.self) { colour in
colour
.body(maxWidth: .infinity, maxHeight: .infinity)
}
.navigationTitle(“Shade”)
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
NavigationStack {     Listing(bgColors, id: .self) { bgColor in          NavigationLink(worth: bgColor) {             Textual content(bgColor.description)         }      }     .listStyle(.plain)      .navigationDestination(for: Shade.self) { colour in         colour             .body(maxWidth: .infinity, maxHeight: .infinity)     }      .navigationTitle(“Shade”) } |
You continue to use NavigationLinks
to current the listing of knowledge and implement the navigation characteristic. What’s distinction is that every NavigationLink
associates with a worth. On high of that, we added the brand new navigationDestination
modifier to seize the worth change. When a consumer selects a specific hyperlink, the navigationDestination
modifier presents the corresponding vacation spot view for navigation hyperlinks that current knowledge of kind Shade
.
For those who take a look at the app within the preview, it really works precisely the identical as earlier than. Nonetheless, the interior implementation already makes use of the brand new navigationDestination
modifier.
A number of Navigation Vacation spot Modifiers
You’re allowed to outline multiple navigationDestination
modifier for dealing with several types of the navigation hyperlinks. Within the earlier instance, we had a single navigationDestination
modifier for the Shade
kind. Let’s say, we’ve one other set of navigation hyperlinks for the String
kind like this:
NavigationLink(worth: systemImage) {
Textual content(systemImage.description)
}
}
.listStyle(.plain)
Listing(systemImages, id: .self) { systemImage in      NavigationLink(worth: systemImage) {         Textual content(systemImage.description)     }  } .listStyle(.plain) |
The systemImages
variable shops an array of the system picture names.
non-public var systemImages: [String] = [ “trash”, “cloud”, “bolt” ] |
On this case, we’ve two varieties of navigation hyperlinks. One is for the Shade
kind, the opposite is the String
kind. To deal with the navigation of the String
kind, we will embed one other navigationDestination
modifier to the stack like this:
.navigationDestination(for: String.self) { systemImage in     Picture(systemName: systemImage)         .font(.system(dimension: 100.0)) } |
Now if the consumer faucets one of many system picture names, it navigates to a different view that shows the system picture.
Working with Navigation States
In contrast to the previous NavigationView
, the brand new NavigationStack
means that you can simply preserve observe of the navigation state. The NavigationStack
view has one other initialization methodology that takes in a path
parameter, which is a binding to the navigation state for the stack:
init( Â Â Â Â path: Binding<Information>, Â Â Â Â root: () –> Root ) the place Information : MutableCollection, Information : RandomAccessCollection, Information : RangeReplaceableCollection, Information.Ingredient : Hashable |
If you wish to retailer or handle the navigation state, you may create a state variable. Here’s a code pattern:
@State non-public var path: [Color] = []
var physique: some View {
NavigationStack(path: $path) {
Listing(bgColors, id: .self) { bgColor in
NavigationLink(worth: bgColor) {
Textual content(bgColor.description)
}
}
.listStyle(.plain)
.navigationDestination(for: Shade.self) { colour in
VStack {
Textual content(“(path.depend), (path.description)”)
.font(.headline)
HStack {
ForEach(path, id: .self) { colour in
colour
.body(maxWidth: .infinity, maxHeight: .infinity)
}
}
Listing(bgColors, id: .self) { bgColor in
NavigationLink(worth: bgColor) {
Textual content(bgColor.description)
}
}
.listStyle(.plain)
}
}
.navigationTitle(“Shade”)
}
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
struct ContentView: View {     non-public var bgColors: [Color] = [ .indigo, .yellow, .green, .orange, .brown ]      @State non-public var path: [Color] = []      var physique: some View {          NavigationStack(path: $path) {             Listing(bgColors, id: .self) { bgColor in                  NavigationLink(worth: bgColor) {                     Textual content(bgColor.description)                 }              }             .listStyle(.plain)              .navigationDestination(for: Shade.self) { colour in                 VStack {                     Textual content(“(path.depend), (path.description)“)                         .font(.headline)                      HStack {                         ForEach(path, id: .self) { colour in                             colour                                 .body(maxWidth: .infinity, maxHeight: .infinity)                         }                      }                      Listing(bgColors, id: .self) { bgColor in                          NavigationLink(worth: bgColor) {                             Textual content(bgColor.description)                         }                      }                     .listStyle(.plain)                  }             }              .navigationTitle(“Shade”)          }      } } |
The code is much like the earlier instance. We added a state variable named path
, which is an array of Shade
, to retailer the navigation state. Through the initialization of NavigationStack
, we go its binding for managing the stack. The worth of the path
variable will likely be mechanically up to date when the navigation stack’s state modifications.
I made a minor change for the navigation vacation spot. It shows the consumer’s chosen colours and exhibits one other listing of colours for additional choice.
Within the code above, we’ve this line of code to show the trail content material:
Textual content(“(path.depend), (path.description)“) |
The depend
property offers you the variety of ranges of the stack, whereas the outline presents the present colour. Say, for instance, you first choose the colour indigo after which additional selects yellow. The worth of depend
is 2, which suggests the navigation stack has two ranges.
With this path
variable, you may programmatically management the navigation of the stack. Let’s say, we will add a button for customers to leap on to the foundation stage of the stack. Right here is the pattern code:
Button { Â Â Â Â path = .init() } label: { Â Â Â Â Textual content(“Again to Major”) } .buttonStyle(.borderedProminent) .controlSize(.giant) |
By resetting the worth of the path
variable, we will instruct the navigation stack to return to the foundation stage.
As it’s possible you’ll already conscious, we will manipulate the worth of the path
variable to regulate the state of the navigation stack. For instance, when the ContentView
seems, the app can mechanically navigate down three ranges by including three colours to the path
variable like this:
NavigationStack(path: $path) { Â Â . Â Â . Â Â . } .onAppear { Â Â Â Â path.append(.indigo) Â Â Â Â path.append(.yellow) Â Â Â Â path.append(.inexperienced) } |
If you launch the app, it mechanically navigates down three ranges. That is how one can management the navigation state programmatically and a good way to deal with deep linking.
Abstract
The brand new NavigationStack
, launched in iOS 16, permits builders to simply construct data-driven navigation UI. In case your app doesn’t have to help older variations of iOS, you may make the most of this new part to deal with deep linking and complicated consumer flows.