Flux in Swift
Facebook have described in depth about their application architecture they call Flux. Since Iâd only seen an implementation in JavaScript, I set out (as a personal software engineering challenge) to write a basic implementation of the idea. This blog post will aim to highlight the key details of that implementation.
Please checkout the source and use the playground to get a feel for Flux.
What is Flux?
Itâs not something you `pod install` and just use. Think of it like âthe new MVCâ. Hereâs a pretty box-and-line diagram from the Flux website.
My key takeaway points about Flux:
- No UI will ever be out of sync with Application State
- No UI race conditions
- Unidirectional data flow (easy to reason about)
- Easily move everything to a background thread (excluding UI)
Store
- Central source of truth for Application State
- Applies mutating functions to Application State
- Subscription service used by Views
Subscription
- A channel that can be observed
- Triggered whenever an update is made to an Entity type
View
- Defines the application state it needs in order to render (ViewState)
- Watches for changes in an Entity (via Store Subscription)
- Updates the UIViews if there is new state
- Wires up interactions to Actions
Entity
- Immutable data representation
- Defines associated actions
Action
- Static function defining a mutation of an Entity (such as set, create, update, delete)
- Called by IBActions, network responses, device status changes, etc.
What does it look like?
Letâs look at a subscription, as defined in a View.
func subscribe() {
store.subscribe(to: .Users, initialiseWith: ViewState.init) {
viewState in self.label.text = viewState.labelText
}
}
This is the Viewâs only access to the outside world. It subscribes to any changes on .Users. If there is an event in the Store, it will pass the new Application State through to a failable function (Iâve opted to use a failable initialiser). If that function returns a value, then it will call the trailing closure with that new state.
What is this ViewState?
Itâs a struct with a failable initialiser, aimed to get a snapshot of the application state, relevant for this View. Every View will have an ViewState.
protocol VS {
init?(data: DataType)
}private struct ViewState: VS {
let labelText: String init?(data: DataType) {
guard let data = data as? [String: User] else { return nil }
self.labelText = /* do something here */
}
}
What does an Entity look like?
struct User {
let id: String
let username: String
}extension User: EntitySetType {
static let subscriptionType = SubscriptionType.Users
static func subscriptionType(id: String) -> SubscriptionType {
return .User(id: id)
}
}
Notice that this Entity is immutable. It is not an object that is passed around and mutated. But rather an immutable snapshot of the current state. It wouldnât make sense to give any other component of your application the ability to change this. If this was mutable, then weâre subject to race conditions for whomever uses this value first. With Flux, none of these race conditions are possible.
What do you do with an Action?
Actions can be called by anything in the application, and are more commonly triggered by user interaction. So we would wire up an IBAction to trigger an update to the Store like so:
func addPostButtonWasPressed() {
let newPost = Post(id: âidâ, content: âcontent")
let action = Post.create(newPost) // just static function
store.dispatch(action)
}
And that is the circle of life!
User Interaction dispatches an
Action that updates the
Store which triggers the
Subscription which gets initialised into a
ViewState which is rendered by the
View
How does that differ from MVC?
If itâs different, is it better?
Whatâs so great?
- Allows for declarative UI classes
- No UI race conditions
- Unidirectional data flow
What problem does this solve?
- View being out of date with the Application State
- Writing complex code in the View that couple life cycle events with Application State (where complexity = unreliability)
- Moving all non-UI events into a background thread is non-trivial
Is this related to React Native?
React is a declarative UI framework which renders application state. Itâs pretty amazing. Here is a 15 minute talk I gave on how this all works.
Thanks for reading. Follow me on Twitter. Check out my other Snippets and Gists.