Exploring the Composable Architecture Framework

Composable Architecture Main Image

At Conjure, our iOS team make a real effort to keep up with the latest trends and technologies when it comes to Swift. With using SwiftUI and Combine, there comes the challenge of efficiently managing state.

A few years ago we attended a talk by Nikita Mounier, where he shared his experiences using the Composable Architecture. In this article, we will give an introduction to this framework.

Overview of The Composable Architecture

The Composable-Architecture, also known as TCA, which is heavily influenced by Redux was developed by Brandon Williams and Stephen Celis from Point-Free. They believe that this framework offers:

  • An opinionated library for building an application in a consistent and understandable way.

  • Focuses on composition, testing and ergonomics.

  • Unilateral state management.

  • Ability to handle side effects.

Data flow diagram of TCA

Data flow diagram of how TCA operates

Components:

State — This is an object that defines the data needed for the logic and UI.

Action — An enum to represent all possible modifications of state.

Reducer — A function that manipulates the properties of the state based on an action.

Environment (Optional) — This is for any dependencies used, for example, a networking module.

Store — The store manages all of the above. It receives an action and runs the reducer to modify the state.

Effect — An event that modifies the state outside of its local context.

Demo project

We created a project using this framework that shows nearby bus stops in London. This data comes from the public TfL API based on the user’s current location.

Project Setup

To use TCA framework, you need to install it into your project. To install the SDK through Swift Package Manager:

Implementation

As part of using the framework, we needed to create an object called BusStopFeature that conforms to ReducerProtocol. This object houses the State, Action and Reducer method.

We really appreciate the way in which it encapsulates these components, as it provides a clear understanding of how the state is modified within this particular module. We also believe that it focuses on the separation of concerns, in terms of individual components such as the state and action. Moreover, using this framework ensures that any modification to the state can only occur within a specific section of the project. We feel this could be vital when it comes down to debugging as everything is centralised.

TCA 2

The BusStopFeature contains two dependencies that are injected using the @Dependencyproperty wrapper. It needs some initial setup to register your dependencies which you can see in TCA+Dependencies.swift in our project.

Walkthrough

To illustrate, let's look at a small example of the overall flow of the architecture. We start when the user interacts with the view, sending an action to the store. A concrete example of this process can be observed in the BusStopView screen when the user taps on a stop. The button triggers the selectStop action passing the selected stop.

TCA 4

The framework provides a method called WithViewStore that enables the view to interact with the store without needing to wrap the store up in an ObservedObject class. Given we are using SwiftUI this helps simplify the code in the view and make it more readable.

After the view sends the selectStop action to the store, this is then passed to the reducer to set the selectedStop property, after which an effect is returned to trigger the setSheet action.

TCA 3

The reducer will then receive the setSheet action and mutate the state again by setting the isSheetPresented. We don’t want to trigger any side effects so we return .none

TCA 5

Once the state has been mutated, the view can listen to the change through WithViewStore and present the sheet. The TCA library allows us to create a binding from the store based on the isSheetPresented property. We can then trigger another action to close the sheet once the user chooses to.

TCA 7

Summary

During the development of this demo project, we found that the flow of TCA provided a clear and intuitive way to understand how the state of the application was being updated. By following the sequence of events, it was easy to trace how the state was being mutated and identify any potential issues.

We have only discussed a small example of using TCA in this article, and there are so many more features that the framework allows.

Overall, we found TCA to be a powerful and effective framework for managing the state in an iOS application. There is obviously a learning process when it comes to using the framework, but we would definitely recommend it to any developer looking to streamline their state management process.

Source code

If you would like to view the source code you can here https://github.com/conjure/demo-ios-tca

Useful links

Previous
Previous

Why Phygital Retail Still Matters

Next
Next

The Intersection of UX and Psychology in Understanding User Behaviour