StateTransition
A swift state machine supporting; states, transitions, actions and transition handling via Combine.
State machine definition
enum StateOfMatter: StateTransitionable {
typealias Action = EnergyTransfer
typealias Context = String
case solid
case liquid
case gas
case plasma
static func defineTransitions(_ stateMachine: StateMachine<EnergyTransfer, StateOfMatter>.TransitionBuilder) {
stateMachine.addTransition(fromState: .solid, toState: .liquid, when: .increase)
stateMachine.addTransition(fromState: .liquid, toState: .gas, when: .increase)
stateMachine.addTransition(fromState: .gas, toState: .plasma, when: .increase)
stateMachine.addTransition(fromState: .plasma, toState: .gas, when: .decrease)
stateMachine.addTransition(fromState: .gas, toState: .liquid, when: .decrease)
stateMachine.addTransition(fromState: .liquid, toState: .solid, when: .decrease)
}
}
enum EnergyTransfer {
case increase
case decrease
}
Example with Combine
func transitionHandler(action: EnergyTransfer, fromState: StateOfMatter, toState: StateOfMatter)->() {
print("transitioned from \(fromState) to \(toState) as result of energy \(action)")
}
let actionSubject = PassthroughSubject<EnergyTransfer, Never>()
let stateChanges = StateOfMatter.solid.publishStateChanges(when: actionSubject.eraseToAnyPublisher())
let cancellable = stateChanges.sink(receiveValue: transitionHandler)
actionSubject.send(.increase)
//prints: transitioned from solid to liquid as result of energy increase
actionSubject.send(.increase)
//prints: transitioned from liquid to gas as result of energy increase
Example without Combine
var stateMachine = StateOfMatter.solid.stateMachine()
guard let transition = stateMachine.perform(action: .increase) else {
return
}
print("transitioned from \(transition.1) to \(transition.2) as result of energy \(transition.0)")
//prints: transitioned from solid to liquid as result of energy increase
stateMachine.perform(action: .increase)
print("current state is \(stateMachine.currentState)")
//prints: current state is gas