Skip to content

Instantly share code, notes, and snippets.

Created October 3, 2017 03:08
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save gbammc/3546ae3b52037756bc3065d9f1fc8f29 to your computer and use it in GitHub Desktop.
import Foundation
protocol StateType: Hashable {}
protocol EventType: Hashable {}
struct Transition<S: StateType, E: EventType> {
let event: E
let fromState: S
let toState: S
init(event: E, fromState: S, toState: S) {
self.event = event
self.fromState = fromState
self.toState = toState
class StateMachine<S: StateType, E: EventType> {
private struct Operation<S: StateType, E: EventType> {
let transition: Transition<S, E>
let triggerCallback: (Transition<S, E>) -> Void
private var routes = [S: [E: Operation<S, E>]]()
private(set) var currentState: S
private(set) var lastState: S?
init(_ currentState: S) {
self.currentState = currentState
func listen(_ event: E, transit fromStates:[S], to toState: S, callback: @escaping (Transition<S, E>) -> Void) {
for fromState in fromStates {
listen(event, transit: fromState, to: toState, callback: callback)
func listen(_ event: E, transit fromState: S, to toState: S, callback: @escaping (Transition<S, E>) -> Void) {
var route = routes[fromState] ?? [:]
let transition = Transition(event: event, fromState: fromState, toState: toState)
let operation = Operation(transition: transition, triggerCallback: callback)
route[event] = operation
routes[fromState] = route
func trigger(_ event: E) {
guard let route = routes[currentState]?[event] else { return }
lastState = currentState
currentState = route.transition.toState
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment