Skip to content

Instantly share code, notes, and snippets.

@altamic
Last active December 27, 2023 08:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save altamic/44869a62c460294d1560c4b7f7285136 to your computer and use it in GitHub Desktop.
Save altamic/44869a62c460294d1560c4b7f7285136 to your computer and use it in GitHub Desktop.
StateMachine in Swift
//
// StateMachine.swift
//
// Created by Michelangelo Altamore on 12/04/2018.
// Copyright © 2018 Michelangelo Altamore. All rights reserved.
//
import Foundation
protocol StateMachineInternals: class {
associatedtype State: Hashable
typealias Block = (() -> Void)
var current: State { get set }
var actions: [Edge<State, State>: Block] { get }
var transitions: [State: [State]] { get }
}
protocol StateMachine: StateMachineInternals {
func go(from current: State, to next: State)
func transact(to next: State)
func move(to newState: State, with userInfo: [WritableKeyPath<Self, String?>: String?]?)
}
extension StateMachine {
func go(from current: State, to next: State) {
guard let currentTransitions = transitions[current],
currentTransitions.contains(next) else {
print("\(Self.self) ERROR: \(current)'s transitions do not include \(next)")
return
}
transact(to: next)
}
func transact(to next: State) {
print("\(Self.self): trying to go from \(current) to \(next)")
guard let nextAction = actions[Edge(from: current, to: next)] else {
print("\(Self.self) ERROR: Could not find Edge from \(current) to \(next)")
return
}
current = next
print("\(Self.self): current state: \(current)")
nextAction()
}
func move(to newState: State,
with userInfo: [WritableKeyPath<Self, String?>: String?]? = nil) {
if let userInfo = userInfo {
for (keyPath, value) in userInfo {
var `self` = self
`self`[keyPath: keyPath] = value
}
}
go(from: current, to: newState)
}
}
struct Edge<A: Hashable, B: Hashable>: Hashable {
let from: A
let to: B
init(from: A, to: B) {
self.from = from
self.to = to
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment