Last active
December 27, 2023 08:00
-
-
Save altamic/44869a62c460294d1560c4b7f7285136 to your computer and use it in GitHub Desktop.
StateMachine in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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