Composable SwiftUI Bindings: The Problem

Episode #107 • Jul 6, 2020 • Subscriber-Only

Bindings are one of the core units of SwiftUI data flow and allow disparate parts of an application to communicate with one another, but they are built in such a way that strongly favors structs over enums. We will show that this prevents us from properly modeling our domains and causes unnecessary complexity in the process.

The Problem
Inventory entry screen
Implementing quantity
Domain modeling
Next time: binding transformations

Unlock This Episode

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


Many months ago we introduced the concept of “case paths”, which serves the same purpose as key paths do for each field of a struct, but instead they work for each case of an enum. At first it may have seem a little abstract, after all, if case paths are so important why didn’t Apple give us first class support for them in Swift?!

But, we were able to show that case paths allow us to abstractly pick apart and isolate parts of enum so that we can write generic algorithms over the shape of a data type. So far our biggest application of this idea has been to the concept of transforming reducers in the Composable Architecture. In particular, if we have a reducer that operates on a small domain of user actions we can transform it into a reducer that works on global actions by using a case path.

That is an example of a generic algorithm that is able to do its job because we hand it a case path for isolating and transforming a single case of an enum. But it’s only the tip of the iceberg, there are lots of applications of case paths just as there are lots of applications of key paths, and today we will start a series of episodes to explore that further.

The Binding type in SwiftUI is one of the most important types in the framework because it facilitates the communication between disparate parts of your application. It allows a change in one corner of your application to be instantly reflected in another part, and whether you are using an @ObservedObject, a @State property wrapper or an environment value, you are ultimately dealing with bindings.

And because Binding is such a fundamental concept in SwiftUI we would also hope that it is a super composable and transformable unit. That is, it should be possible to take existing bindings and derive all new ones using some simple operators and constructions. And indeed, SwiftUI does ship with a few ways to transform bindings, and it’s actually incredibly powerful.

However, unfortunately, the transformations provided are only half of the picture. All of the tools provided to us out of the box are heavily geared towards structs and more generally what are known as “product” types, mostly because the tools leverage the power of key paths. The tools for properly dealing with enums and sum types are simply absent, which means that it is difficult or impossible to model our domains in a precise manner, which leads to a lot of unnecessary complexity.

Well, soon we will fix this deficiency in SwiftUI’s toolset, and of course case paths are going to play a big part in accomplishing this because they are the perfect tool for generically working with enums.

But to begin, let’s first get a better understanding of how bindings work and what are the ways we can transform them right out of the box in SwiftUI.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in