Unlock This Episode
Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.
Brandon: Today we are excited to begin a series of episodes that is probably the most highly anticipated topic for Point-Free, and that is navigation tools for our popular library: the Composable Architecture.
We’ve hinted at this series many times in the past, but it was never quite the right time to embark on the journey. There were two really big things that needed to be accomplished first:
The Composable Architecture library itself needed some modernization improvements:
We needed to more deeply integrate Swift’s amazing new concurrency tools into the library. In doing so, one can now create effects using async-await, and it’s easy to tie the lifetime of effects to the lifetime of views.
We also revamped how one builds features in the library by putting a protocol in front of the concept of a “reducer”. This allowed us to leverage a result builder-like syntax for composing complex features.
And finally we introduced a brand new dependency management system, which makes it easy to push dependencies deep into an application. We even extracted that system into its own library so that it can be used in vanilla SwiftUI, UIKit, AppKit, and even server applications.
So, modernizing the Composable Architecture was the first big thing we needed to accomplish. The second was we needed to conclude our extensive series discussing SwiftUI navigation from first principles since recently iOS 16 had some pretty big changes. We covered the new binding-driven
navigationDestinationAPI as well as the new collection-based
NavigationStackAPI. We were even able to work around a few SwiftUI navigation bugs along the way, but there are still more lurking in the shadows.
But the best part of all of that work is that we came across something that we like to call the “grand unified theory” of SwiftUI navigation. We found that basically all forms of navigation in SwiftUI can be united with very similar APIs. Everything from alerts, sheets and popovers, to even drill downs. And that was incredible to see, and really helps clear the fog when it comes to the complexities of navigation.
Brandon: With all of that foundational work completed we are now ready to start layering on navigation tools in the Composable Architecture. Once we are done we will find that if you put in a little upfront domain modeling work when creating your features, you will unlock some amazing super powers. Most, if not all, of the problems we encountered when dealing with vanilla SwiftUI are fixed in the Composable Architecture, and we have access to all new capabilities that we couldn’t even have dreamed of with vanilla SwiftUI!
So, let’s get started.
Our favorite way of managing parent-child communication in “modern” SwiftUI.
We add more screens and more navigation to our rewrite of Apple’s Scrumdinger, including the standup detail view, a delete confirmation alert, and we set up parent-child communication between features.
Krzysztof shows off a few patterns in the Composable Architecture, including “delegate” actions:
To maintain our codebases for years, we must create boundaries across modules. Here’s my approach to doing that with The Composable Architecture.
GitHub search results for
DelegateAction in isowords, demonstrating the pattern of child-to-parent communication, where the child domain carves out a bit of its domain that makes it clear to the parent which actions are important to listen for.
There is a common pattern of using actions to share logic across multiple parts of a reducer. This is an inefficient way to share logic. Sending actions is not as lightweight of an operation as, say, calling a method on a class. Actions travel through multiple layers of an application, and at each layer a reducer can intercept and reinterpret the action.