LAST CHANCE: Save 50% on all my Swift books and bundles! >>

How to use programmatic navigation in SwiftUI

Paul Hudson    @twostraws   

Updated for Xcode 13.0

We can use SwiftUI to programmatically push a new view onto a NavigationView using NavigationLink, meaning that we can trigger the navigation when we’re ready rather than just when the user tapped a button or list row.

There are two ways of doing this, both of which rely on initializers for NavigationLink. The first is binding the NavigationLink to a Boolean state – when that Boolean becomes true the navigation will happen immediately, and when it becomes false again the new view will be dismissed.

SwiftUI does require that we pass some sort of view to NavigationLink even when doing programmatic navigation. You’ll probably want to use EmptyView to show nothing at all, for example here’s a complete example of programmatic navigation, where I’m toggling the Boolean on a button press:

struct ContentView: View {
    @State private var isShowingDetailView = false

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: Text("Second View"), isActive: $isShowingDetailView) { EmptyView() }

                Button("Tap to show detail") {
                    isShowingDetailView = true
                }
            }
            .navigationTitle("Navigation")
        }
    }
}

Download this as an Xcode project

The advantage to this approach over a simple NavigationLink is that our button can do any amount of other work before triggering the programmatic navigation – maybe you want to save some data, or authenticate the user, etc.

If you have several possible destinations, you can bind more than one NavigationLink to some selection state, giving each one a unique tag. When you update your selection state to match one of those tags will cause the appropriate NavigationLink to activate, which gives you multi-destination programmatic navigation without having lots of Booleans.

For example, this navigates to one of two destination text views depending on the value of a selection property:

struct ContentView: View {
    @State private var selection: String? = nil

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: Text("View A"), tag: "A", selection: $selection) { EmptyView() }
                NavigationLink(destination: Text("View B"), tag: "B", selection: $selection) { EmptyView() }

                Button("Tap to show A") {
                    selection = "A"
                }

                Button("Tap to show B") {
                    selection = "B"
                }
            }
            .navigationTitle("Navigation")
        }
    }
}

Download this as an Xcode project

Click here to save 50% on all my books and bundles!

Similar solutions…

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 5.0/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.