Shared State: User Defaults, Part 1

Episode #273 • Apr 1, 2024 • Subscriber-Only

Let’s enhance the @Shared property wrapper with the concept of persistence. We will begin with user defaults, which is the simplest form of persistence on Apple’s platforms, and that will set the stage for more complex forms of persistence in the future.

Previous episode
Shared State: User Defaults, Part 1
Next episode

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Sign in with GitHub



OK, this is all looking absolutely incredible. We have now seemingly fixed all of the problems we encountered with sharing state, and so we can now full heartedly and strongly recommend representing simple shared state in your applications as a reference type. Historically it would have been quite problematic to put a reference in a Composable Architecture feature, for two main reasons:

Reference types used to not play nicely with view invalidation, and so you could make changes to the data in the reference and that would not cause the view to re-render. That is no longer a concern thanks to Swift’s new observation tools.


And second, reference types are not easy to test and debug since you can’t capture the before and after values to compare. But we have now fixed that thanks to the Shared type and some new internal logic inside the TestStore.

Now everything we have accomplished so far is fantastic, and we could stop here and have a very compelling story for how to share state amongst features in the Composable Architecture. But we can make things even better.


Sometimes we want shared state to be very explicit and localized. This is how our case study is structured right now, and how we approached the complex sign up flow a few episodes back. If a feature wants a piece of shared state, it must use the @Shared property wrapper, and whoever creates that feature must pass along a piece of shared state.

But sometimes we want shared state to be ubiquitous throughout the application. Any feature should be able to reach out and grab the shared state immediately without it being passed around explicitly, and should be able to make changes to that shared state.


The prototypical example of this is settings. Settings is usually state that the entire app needs to be able to access, and that perhaps a few features also need to be able to write to. If we stopped with shared state as it is right now we would have to explicitly pass around Shared values to every feature that needs settings. And this is a viral situation. If some deep leaf feature needs access to settings, then every parent feature needs to also hold onto a Shared settings object just to pass it along, even if it doesn’t care about settings.

Let’s see what it takes share state across the entire application, instantly.

Ubiquitous shared state


Get started with our free plan

Our free plan includes 1 subscriber-only episode of your choice, access to 62 free episodes with transcripts and code samples, and weekly updates from our newsletter.

View plans and pricing