Unlock This Episode
Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.
So, we have now had 8 entire episodes on navigation in SwiftUI: 2 on just tab views and alerts, 3 on sheets and popovers, and 3 on navigation links. We didn’t expect it to take this long to cover these basic forms of navigation in SwiftUI, but here we are.
Along the way we dove deep into the concepts of driving navigation from state, most importantly optional and enum state, which forced us to construct all new tools for abstracting over the shape of enums, such as case paths. We’ve seen that if you treat navigation primarily as a domain modeling problem, and if you have the tools necessary for modeling your domain, there are a ton of benefits to reap. We instantly unlock the ability to deep link into any part of our application, and it’s as simple as building a nested piece of state that describes exactly where you want to navigate to, hand it off to SwiftUI, and let it do the rest.
And, for free, we also get to test more of our application by asserting on how independent pieces of the application interact with each other.
While exploring these topics we’ve also seen that we had to give up some of SwiftUI’s tools in order to embrace our goals of deep linking and testability. For example, although using local
@State in views can be really handy, the moment you do you lose the ability to influence that state from the outside, which means it’s not possible to deep link into those states or test how those states influence your application. And although we didn’t discuss it in this series of episodes, the same applies to
Another example of a SwiftUI tool we had to give up was using SwiftUI’s “fire-and-forget” navigation patterns, such as the initializers on
NavigationLink that do not take bindings. Those tools allow us to get things on the screen very quickly, but sadly are not helpful if we need to deep link or write tests.
But now that we are done with the core series on navigation, we’d like to add one more thing. We’ve paid a lot of lip service to deep linking, and we’ve showed how it’s theoretically possible by constructing a large piece of state, handing it to the view, and then letting SwiftUI do its thing, but we haven’t shown how one could add actual, real world deep linking to the application. That is, how does one actually intercept a URL in order to parse it, understand what destination in your application it represents, and then actually navigate to that place.
Add a deep linker route for duplicating an item.
inventoryDeepLinkerto group the “add” and “color picker” routes so that the
addpath component is parsed at most a single time.
Add the ability to deep-link into the edit and duplicate screens and further pre-fill fields and link further into the color picker screens. Try to re-use the
itemparser to handle these routes.
Note that parsing
Items as is will prevent you from deep-linking to edit or duplicate and overriding a single field. Instead, introduce a new data structure that allows you to selectively override an
After 9 episodes exploring SwiftUI navigation from the ground up, we open sourced a library with all new tools for making SwiftUI navigation simpler, more ergonomic and more precise.
A library for turning nebulous data into well-structured data, with a focus on composition, performance, generality, and invertibility.
The ability to break down applications into small domains that are understandable in isolation is a universal problem, and yet there is no default story for doing so in SwiftUI. We explore the problem space and solutions, in both vanilla SwiftUI and the Composable Architecture.