State Machine

/*
Simple State Machine in Swift
https://blog.lukaskukacka.com/swift/2018/10/08/simple-state-machine-in-swift.html
*/

public protocol StateMachine {

    /// represents a State of a state machine. 
    /// this will most likely be an enum. 
    /// it is `Hashable` so it can be stored in a `Set`
    /// of allowed state transitions.
    associatedtype State: Hashable

    /// current state of a state machine
    var state: State { get set }

    /// states transitions dictionary.
    /// contains set of allowed next states for each state.
    static var transitions: [State: Set<State>] { get }

    /// determines whether the transition to next state is allowed
    /// from current state.
    func canTransition(to nextState: State) -> Bool

    /// performs the transition of a state machine to next state.
    /// it is marked as mutating because it mutates the state.
    mutating func transition(to nextState: State)

}

// default implementation
extension StateMachine {

    // self.canTransition(to: nextState)
    func canTransition(to nextState: State) -> Bool {
        return Self.transitions[state]?.contains(nextState) ?? false
    }

    // self.transition(to: nextState)
    mutating func transition(to nextState: State) {

        guard canTransition(to: nextState) else {
            print("\nโ›” Invalid state transition: \n\t\(state) -> \(nextState)")
            return
        }
        
        print("\n\(type(of: self)) is about to change state:\n\t\(state) -> \(nextState)")
        self.state = nextState
    }

}

Last updated