TCA: Using Composable Architecture for creating an Expandable Picker

Being on the way of working with TCA in a potentially large application, the benefits of using TCA become more and more obvious in a variety of scopes.

In this article, I’d like to share my experience in “Thinking TCA” by building a small component that presents a row that can be tapped; when tapped, it expands and shows a picker for a set of values; after picking a value, the row display is updated. And the row can be collapsed, certainly…

Image for post
Image for post
Image for post
Image for post
Image for post
Image for post
The workflow with the expandable picker

Usually, I’d approach this by first creating an empty view, adding a var for the expansion status, adding a subview for the expandable row, adding a picker to the expanded content, adding properties for the picker’s content, and adding a var for the picker’s index. Pretty straightforward.

With TCA, I tried to convert that top-down approach to States, Actions and Reducers, and I created a pretty complicated bundle for that view. Which I didn’t like. The separation of concerns was hurt, and fixing that was not so nice.

So, I tried to think bottom-up. What is the first view we need?

The very first view I created was the .

For TCA, we need a store first. The row has to states, collapsed and expanded. So a value is fully sufficient as TCA State.

What actions do we need? The Row simply reacts on a tap, so we need an action that is triggered by .

Independent of the state, we’ll present a placeholder that is an injected view; if the state is set to , we’ll show the injected content view.

Now, for TCA, we need an action and a reducer. How do they look like?

The TCA Action is pretty simple. The reducer is it as well, we just invert the current state (which is, you’ll remember, a ).

Now, we can use the view in a preview and see, if it works:

So, we’re done with that component. What next?

When the row is expanded, we want to see a picker. So, the injected to the view must be some kind of picker.

Here, again, we have a TCA Store, an injected placeholder view, and a with an

To fully understand the picker’s call, let’s dive into the other TCA stuff:

The picker needs a , which we provide as , and a list of , provided as array of .

Because the picker shall modify the , we need a binding. The TCA framework provides a special feature for the where the current value is handed to the picker using the property, and the action to be triggered by the picker when changing the value is provided by the property.

The values are a simple loop over the of the .

Here, again, we can check that it’s working by using a preview:

The TCA Action now has a parameter, the index provided by the picker. The reducer therefore has to react on that action by setting the state’s to the provided .

Obviously, you’ll see… nothing, so you may want to run the preview in debug mode and add a statement to the action, to see that the really changes.

Again, a standalone component without any dependencies, except the injected `placeholder` view.

Now we have to combine both views, the and the in order to get our final view.

This is how the view looks like:

Here again, we need a TCA store with a state and an action definition. With the , we can then use the where the provides the .

We now could provide the stores for the subview by using the standard initializer with . However, if we do that, those views are completely independent: We cannot react here on changes there.

So, instead we need to use the . To understand this, we have a look on the remaining TCA definitions:

What we see here is that we have a reducer, that combines the two reducers from the subviews by a of their actions. To have this work, we need two meta actions and with the respective subactions as parameter.

We may want to combine this with a reducer where we can react on whatever happens in the subviews (in this case: some statements).

So, by using the statement, we enable our reducer to access those of the subviews, and with the and operations, we can react here on what happens below.

Here again, we can check using a preview if everything’s working as expected:

This concludes our journey to another TCA application that gives us an expandable item picker that we can use itself as a component in a larger context, like we did here with the and the . This makes clear, how transparent and easy large and complex application can be built using TCA, while keeping each component as isolated as possible.

I hope this is another step for your to better understand the benefits of TCA. Let me know if it was helpful for you, or if you have suggestions for more reflections.

Helping companies and humans to evolve, and trying to be agile in an own product development.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store