Member-only story
Decoupling Navigation in SwiftUI
How to move your Navigation Flow away from your View Code
SwiftUI is a great way to build modern, interactive UIs. While it lacks some features that still need to be wrapped via UIKit, it is mature enough to be used in production for a good while now. But one thing that is still cumbersome to do is navigation — explicitly making the View irresponsible for navigation. This article will show a simple way to decouple your navigation from view logic. No UIKit required.

NavigationLink
NavigationLinks are the primary source of navigation in SwiftUI. While they offer a simple yet elegant way to handle navigation in our apps, they can become quite limiting when navigation flow gets more complex.
Let’s look at the most simple NavigationLink for now.

When the user taps on the content passed via label
the link is triggered, and the NavigationView pushes destionation
onto the View Stack. While this is fine for some cases, it already shows one big drawback: We cannot control when we want to navigate; the link is triggered immediately on tap. Another disadvantage is that we can only pop the new View when interacting with the default back action provided by iOS. That can become a problem. The only way for us to handle navigational events is onDisappear
and onAppear
.
Now with States
To solve the first drawback, we can instead rely on State and trigger NavigationLinks via bindings. NavigationLink has another init which allows us to pass an additional parameter, isAcvtive
. When it changes State, the NavigationLink pushes or pops the View given via destionation
. That is especially helpful when we need to issue commands, like a database request, before navigation.

We could also wait for a backend call to finish or not toggle the State at all if a check or response fails. States are an excellent way for managing NavigationLinks, but one drawback stays the…