> ## Content Index
> Fetch the complete content index at: https://albertodebortoli.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# The easiest State Machine in Swift
- URL: https://albertodebortoli.com/2018/12/16/the-easiest-state-machine-in-swift/
- Published: 2018-12-16T23:01:49.000Z
- Updated: 2019-04-12T19:24:10.000Z
- Author: Alberto De Bortoli
- Tags: iOS, state machine, swift

Here's another article of the serie "The easiest <something>". Previous ones on Core Data ([The easiest Core Data](https://albertodebortoli.com/2016/08/05/the-easiest-core-data/)) and Future and Promises ([The easiest promises in Swift](https://albertodebortoli.com/2018/02/12/the-easiest-promises-in-swift/)).

It was a cold Sunday afternoon when I decided to bring to Swift my [ADBStateMachine](https://github.com/albertodebortoli/ADBStateMachine?ref=albertodebortoli.com) implemented in Objective-C right about 5 years ago. Actually, it was... today, 16/12/2018.

# Stateful 🦜

Here it is [Stateful](https://github.com/albertodebortoli/Stateful?ref=albertodebortoli.com), a minimalistic, thread-safe, non-boilerplate and super easy to use state machine.

Stateful is available through [CocoaPods](https://cocoapods.org/?ref=albertodebortoli.com) and under the MIT license.

## What is a state machine

I'm pretty much assuming the reader knows what a [state machine](https://en.wikipedia.org/wiki/Finite-state%5Fmachine?ref=albertodebortoli.com) is. It's is a mathematical model of computation, an abstract concept whereby the machine can have different states, but at a given time fulfills only one of them.

![state-machine-example](https://storage.ghost.io/c/ae/f4/aef4d625-32a2-417b-86f4-22c70a9b47a1/content/images/2018/12/state-machine-example.png)

- State machines have an initial state
- Other states can be reached via transitions from previous states
- Transitions are performed in reaction to events

## Example

Let's see how to user Stateful with a concrete example.

First, you should define the events and statuses you need. From the image above:

```swift
enum EventType {
    case click
    case success
    case failure
    case retry
}

enum StateType {
    case idle
    case fetching
    case error
}

```

Create a state machine with the initial state (you might want to retain it in a property)

```swift
let stateMachine = StateMachine<StateType, EventType>(initialState: StateType.idle)

```

`StateMachine` will use the main queue to execute the transition pre and post blocks but you can optionally provide a custom one.

```swift
let dispatchQueue = DispatchQueue(label: "com.albertodebortoli.someSerialCallbackQueue")
let stateMachine = StateMachine<StateType, EventType>(initialState: StateType.idle, callbackQueue: dispatchQueue)

```

Create transitions and add them to the state machine (the state machine will automatically recognize the new states).

```swift
let t1 = Transition<StateType, EventType>(with: .click,
                                          fromState: .idle,
                                          toState: .fetching)
                    
let t2 = Transition<StateType, EventType>(with: .success,
                                          from: .fetching,
                                          to: .idle)

let t3 = Transition<StateType, EventType>(with: .failure,
                                          fromState: .fetching,
                                          toState: .error,
                                          preBlock: {
                        print("Going to move from \(StateType.fetching) to \(StateType.error)!")
                                       }, postBlock: {
                        print("Just moved from \(StateType.fetching) to \(StateType.error)!")
    })
                  
let t4 = Transition<StateType, EventType>(with: .retry,
                                          fromState: .error,
                                          toState: .fetching)

stateMachine.add(transition: t1)
stateMachine.add(transition: t2)
stateMachine.add(transition: t3)
stateMachine.add(transition: t4)

```

Process events like so

```swift
stateMachine.process(event: .start)
stateMachine.process(event: .pause, callback: { result in
    switch result {
    case .success:
        print("Event 'pause' was processed")
    case .failure:
        print("Event 'pause' cannot currently be processed.")
    }
})

```

### Logging

You can optionally enable logging to print extra state change information on the console

```swift
stateMachine.enableLogging = true

```

Example:

```
[Stateful 🦜]: Processing event 'start' from 'idle'
[Stateful 🦜]: Processed pre condition for event 'start' from 'idle' to 'started'
[Stateful 🦜]: Processed state change from 'idle' to 'started'
[Stateful 🦜]: Processed post condition for event 'start' from 'idle' to 'started'
[Stateful 🦜]: Processing event 'stop' from 'started'
[Stateful 🦜]: Processed pre condition for event 'stop' from 'started' to 'idle'
[Stateful 🦜]: Processed state change from 'started' to 'idle'
[Stateful 🦜]: Processed post condition for event 'stop' from 'started' to 'idle'

```

# Conclusions

State machines come handy even to these days when the world seems to have moved to a more stateless way of doing things. Whenever you need to explicitly surface statuses, transition to a different state as a reaction of an event, and possibly leter recover state, a finite state machine might come handy.

Good examples that come to mind are:

- manage overall application state
- ease deeplinking implementation
- ease UI testing

🦜🦜🦜

Special thanks to [Matteo Comisso](https://github.com/mcomisso?ref=albertodebortoli.com) for contributing to Stateful adding [support for Generics](https://github.com/albertodebortoli/Stateful/pull/1?ref=albertodebortoli.com).