Swift & Redux: Basics

czater
Mac O’Clock
3 min readApr 30, 2020

--

Redux is an app architecture based on the idea of a single source of truth — it can be either a single struct or composition of structs — that is accessible from any place within the app. It was created in 2015 by Dan Abramov and Andrew Clark and has since then been widely used in the frontend world. The popularity of Redux in the mobile world highly increased with the appearance of the first-party reactive UI frameworks such as Flutter and SwiftUI because they work together very well.

Redux is built from several elements: state, action, reducer, and store.

The state is a container for all the information needed by our app. It can be read directly but cannot be modified directly. To change it we have to use actions. An action represents a state mutation — it could be a simple enum, struct or class, that holds new information that will be added to the state. Reducer is a pure function that takes two parameters — an action and current state — and returns a new state. A store is an object that holds state and exposes methods to read & modify it. Let’s now take a look at the minimal implementation example.

struct AppState {
var counter: Int
}

An AppState contains only a counter variable that can be modified using the below actions.

enum AppAction {
case add(value: Int)
case subtract(value: Int)
}

An AppAction enum contains only two actions with associated value — add and subtract.

func appReducer(state: inout AppState, action: AppAction) -> AppState {
switch action {
case .add(let value):
state.counter += value
case .subtract(let value):
state.counter -= value
}
return state
}

An appReducer function utilises the app’s state and actions to add or subtract value to the state’s counter.

class AppStore {
private(set) var state: AppState

init(state: AppState = .init(counter: 0)) {
self.state = state
}
public func dispatch(action: AppAction) {
state = appReducer(state: &state, action: action)
}
}

An AppStore contains a state variable that is readable but not modifiable directly — exactly as it should be. A dispatch function makes the state modification possible.

Let’s try to use all these pieces together.

let store = AppStore()
print(store.state.counter) //0
store.dispatch(action: .add(value: 5))
print(store.state.counter) //5
store.dispatch(action: .subtract(value: 3))
print(store.state.counter) //2

It works like a charm.

In conclusion, Redux is a well-defined app architecture with multiple advantages, such as prediction — for the same set of actions, the same new state is going to be generated, centralisation — an app’s state with all the needed tools in one place, and testability — tests are extremely easy to write and perform.

Of course, it is not free from flaws as well. Memory usage might be high when the state is very complex which could lead to poor app performance. Also, it might be hard to implement Redux in the iOS world in some specific scenarios — i.e. in the camera app.

--

--