SwiftUI Navigation Is a Mess. Here’s What You Can Do

Managing navigation in pure SwiftUI is hard and leads to messy solutions. In this post, I will show you how you can manage views effectively

Alex Dremov
SwiftUI Navigation Is a Mess. Here’s What You Can Do

Photo by Mick Haupt / Unsplash

Why messy?

It's because of the core idea of SwiftUI — a view is a function of the state, or a view is state-driven. Don't get me wrong, this concept is great, but SwiftUI's navigation is not this advanced yet.

💡
The view is a function of the state and navigation is not an exception

However, SwiftUI does not have the means to construct robust navigation inside your app.

Messy example

Consider the common case of the onboarding screen when you need to present some sequence of views with nice transitions. What can you do with SwiftUI? Probably, create an enum that tells which screen is active and then use switch to present the sequence of views.

0:00
/

What if you need to modify the order or change the number of views? You'll need to modify the corresponding enum, modify the logic of switching inside the views, and other stuff.

Not so flexible, right?

Oh, and then you decide to present one view right in the middle through .sheet. That's when the mess starts to show up. You create an additional @State to check if the sheet is open, make sure that it's updated correctly, and restructure the switch block that you used before.

Now, it's a chaotic view that is prone to unexpected bugs.

Existing navigation views

The most obvious one is NavigationView which is deprecated in the new iOS 16.

Image by https://developer.apple.com/documentation/swiftui/navigationview

Using NavigationLink, it can present new views and also adds a "back" button to return to the previous view.

And it does not support programmatic navigation.

Apple presented a new NavigationStack that addresses this issue but it is still not flexible enough. For example, I like to have the ability to modify the view whatever I want, but NavugationStack inserts back buttons. Also, it does not support different transitions. While it is nice to see SwiftUI develop in this direction, yet we are not there.

So, even in iOS 16, SwiftUI is not powerful enough to manage any kind of navigation you can come up with.

And .sheet(). NavigationStack does not make it easier to handle .sheet() either.

Designing a flexible navigation library

I decided to create a library with several requirements:

  • Programmatic views navigation
  • Ability to present a sequence of views
  • Support for any SwiftUI transition and Animation
  • Completely state-driven: no singletons or environment objects
  • Handle .sheet()

Sounds cool, right?

Straight to the point, I was able to create such a library.

GitHub - AlexRoar/PathPresenter: Pure SwiftUI state-driven library to present view sequences and hierarchies.
Pure SwiftUI state-driven library to present view sequences and hierarchies. - GitHub - AlexRoar/PathPresenter: Pure SwiftUI state-driven library to present view sequences and hierarchies.
💡
I am always open to objective criticism and requests for a new feature. Do not hesitate to open an issue on GitHub!

So, if you just want a nice tool for the things I listed above, you can stop here. Now, let's see how I did it.

Ways to present

At the core of the library is a structure that stores views and information about how to present them. Possible options for presentation are

enum PathType {
    /**
    * Just show a view. No animation, no transition.
    * Show view above all other views
    */
    case plain

    /**
    * Show view with in and out transitions.
    * Transition animation also can be specified.
    */
    case animated(transition: AnyTransition, animation: Animation)

    /**
    * Show view in .sheet()
    */
    case sheet(onDismiss: Action)
}
Note that presenting through .sheet() is as easy as just presenting any other view.

So, you can present the view without any animation, present it with needed transitions, and present it in a sheet.

Path

This structure stores information about views. It just stores an array of type-erased views with presentation type information. You can append views on top and remove them from the top.

Share

Subscribe to Alex Dremov

Get the email newsletter and receive valuable tips to bump up your professional skills