SwiftyStateSignals is a simple finite state machine framework inspired by StateSignals and built on ReactiveCocoa signals.
SwiftyStateSignals can be imported just like any framework, but is easy to use with Carthage. Just add the following to your Cartfile:
github "simonyangme/SwiftyStateSignals"
Begin by defining enums for states:
enum TurnstileState {
case Locked, Unlocked
}
and events:
enum TurnstileEvent {
case Coin, Push
}
Then create a transition dictionary with the desired transitions and create the state machine:
let transitions = TransitionDictionary<TurnstileState, TurnstileEvent>()
transitions.mapEvent(.Coin, fromState: .Locked, toState: .Unlocked)
transitions.mapEvent(.Push, fromState: .Unlocked, toState: .Locked)
let machine = SignalMachine(transitionDictionary: transitions, withInitialState: .Locked)
We can observe for changes by subscribing to any of the signals that the state machine vends. For example:
machine.allTransitions().observe(next: { transition in
NSLog("Observed an event")
// Do stuff here
})
machine.transitionFaults().observe(next: { transition in
NSLog("Invalid event; no transition occurred")
// Do other stuff here
})
Transitions are defined as such:
struct Transition<State, Event> {
let fromState: State
let toState: State?
let event: Event
}
Transitions are Printable
, but will only display Enum Value
for your states and events if they are not. To pretty print transitions, make your enums Printable, like so:
enum TurnstileState: Printable {
case Locked, Unlocked
var description: String {
get {
switch self {
case .Locked:
return "Locked"
case .Unlocked:
return "Unlocked"
}
}
}
}
enum TurnstileEvent: Printable {
case Coin, Push
var description: String {
get {
switch self {
case .Coin:
return "Coin"
case .Push:
return "Push"
}
}
}
}
machine.allTransitions().observe(next: { t in
NSLog("\(t)")
})
machine.inputEvent(.Coin)
will print:
Transition: Locked -> Optional(Unlocked), Event: Coin