Unlock This Episode
Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.
So this is pretty cool. Using some pretty advanced techniques from SwiftUI we have been able to build tools for the Composable Architecture that allow us to embrace better data modeling for our applications. We can now use enums for our state and emulate the idea of destructuring a store by using a
SwitchStore view with a bunch of
CaseLet views inside. We can even provide some basic support for exhaustivity checking so that if the state gets into a case that is not handled by a
CaseLet view we will breakpoint to let the developer know there’s additional state to handle. And on top of all that we’ve even made the view efficient by making sure it recomputes its body if and only if the case of the enum changes.
We can even push some of these ideas a bit further. With a little bit of extra work you can also support default-like statements for
SwitchStore. This can be handy if you have a lot of cases in your enum and you want to handle only a few while allowing all the others to fall through to a default view. We have some exercises for this episode that will help you explore these ideas.
In the past 4 episodes we have really dug deep into the concept of “deriving behavior”, which means how do we take a big blob of “behavior” for our application and break it down into smaller pieces. This is important for building small, understandable units for your application that can be plugged together to form the full application, as well as for modularizing your application which comes with a ton of benefits.
We started this exploration by first showing what this concept looks like in vanilla SwiftUI by using
ObservableObjects. Apple doesn’t give us direct tools to be used for this problem, but we are able to use some tools from Combine in order to break down large view models into smaller domains. We got it to work, but it wasn’t exactly pretty. We had to do extra work to get the parent domain to update when a child domain changed, and we had to do some trickery to synchronize changes between sibling child domains without introducing memory leaks or infinite loops.
Then we turned our attention to the Composable Architecture. We showed that out of the box the library gives us a tool for breaking down large pieces of application logic into smaller pieces, which is the
.pullback operator on reducers. And the library gives us a tool for breaking down large runtimes, which is the thing that actually powers our views, into smaller pieces by using the
.scope operator on stores. These two tools allowed us to build features in isolation without any understanding of how they will be plugged into the larger application, and then it was trivial to integrate child feature into parent features.
Once we got a feeling for how pulling back and scoping work in the Composable Architecture we started flexing those muscles more. We started exploring tools that allow us to embed our domains into a variety of data structures, such as collections, optionals and enums. This includes using reducer operators such as the
.forEach operator that allows you to run a reducer on every element of a collection, the
.optional operator that enhances a reducer to work on optional state, and even a new version of
.pullback that pulls back along state case paths for when your state is an enum. Corresponding to each of those reducer operators were new SwiftUI views for transforming the store, such as the
IfLetStore and even
That was all pretty amazing, but now it’s time to ask: what’s the point? This is our opportunity to try to bring things down to earth and maybe even dig in a little deeper. This time we want to end this series of episodes like we started: we want to show what one must do in vanilla SwiftUI to handle things like collections of domains and optional domains so that we can better understand how it compares to the Composable Architecture and see why it is important to have tools that are tailored for these use cases.
So, let’s try building our demo app with the collection of counters and fact banner in vanilla SwiftUI…next time!