Skip to content

Instantly share code, notes, and snippets.

@kingnight
Forked from gbammc/StateMachine.swift
Created March 8, 2019 10:54
Show Gist options
  • Save kingnight/03528a4c08b04a907077e6abf2413675 to your computer and use it in GitHub Desktop.
Save kingnight/03528a4c08b04a907077e6abf2413675 to your computer and use it in GitHub Desktop.
StateMachine
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 }
route.triggerCallback(route.transition)
lastState = currentState
currentState = route.transition.toState
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment