Unlock This Episode
Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.
Introduction
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 @StateObject
s too.
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 TabView
and 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.
Subscribe to Point-Free
Access this episode, plus all past and future episodes when you become a subscriber.
Already a subscriber? Log in
Exercises
Add a deep linker route for duplicating an item.
Refactor the
inventoryDeepLinker
to group the “add” and “color picker” routes so that theadd
path 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
ItemRoute
anditem
parser to handle these routes.Note that parsing
Item
s 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 anItem
’s fields.
References
SwiftUI Navigation
Brandon Williams & Stephen Celis • Tuesday Nov 16, 2021After 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.
Swift Parsing
Brandon Williams & Stephen Celis • Tuesday Dec 21, 2021A library for turning nebulous data into well-structured data, with a focus on composition, performance, generality, and invertibility.
Collection: Derived Behavior
Brandon Williams & Stephen Celis • Monday May 17, 2021The 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.