Skip to content

Instantly share code, notes, and snippets.

@jemmons
Created February 2, 2015 15:05
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jemmons/c9434cc09831a276003e to your computer and use it in GitHub Desktop.
Save jemmons/c9434cc09831a276003e to your computer and use it in GitHub Desktop.
import Foundation
class StateMachine<P:StateMachineDelegateProtocol>{
private unowned let delegate:P
private var _state:P.StateType{
didSet{
delegate.didTransitionFrom(oldValue, to:_state)
}
}
var state:P.StateType{
get{ return _state }
set{
if delegate.shouldTransitionFrom(_state, to:newValue){
_state = newValue
}
}
}
init(initialState:P.StateType, delegate:P){
_state = initialState
self.delegate = delegate
}
}
protocol StateMachineDelegateProtocol: class{
typealias StateType
func shouldTransitionFrom(from:StateType, to:StateType)->Bool
func didTransitionFrom(from:StateType, to:StateType)
}
class MyClass{
private var machine:StateMachine<MyClass>!
enum AsyncNetworkState{
case Ready, Fetching, Saving
case Success(NSDictionary)
case Failure(NSError)
}
init(){
machine = StateMachine(initialState: .Ready, delegate: self)
}
}
extension MyClass:StateMachineDelegateProtocol{
typealias StateType = AsyncNetworkState
func shouldTransitionFrom(from:StateType, to:StateType)->Bool{
switch (from, to){
case (.Ready, .Fetching), (.Ready, .Saving),
(.Fetching, .Success), (.Fetching, .Failure),
(.Saving, .Success), (.Saving, .Failure):
return true
case (_, .Ready):
return true
default:
return false
}
}
func didTransitionFrom(from:StateType, to:StateType){
switch (from, to){
case (.Ready, .Fetching):
MyAPI.fetchRequestWithCompletion(handleRequest)
case (.Ready, .Saving):
MyAPI.fetchRequestWithCompletion(handleRequest)
case (_, .Failure(let error)):
displayGeneralError(error)
machine.state = .Ready
case (.Fetching, .Success(let json)):
parseFetchSpecificJSON(json)
machine.state = .Ready
case (.Saving, .Success(let json)):
parseSaveSpecificJSON(json)
machine.state = .Ready
case (_, .Ready):
updateInterface()
default:
break
}
}
}
private extension MyClass{
func handleRequest(json:NSDictionary, error:NSError?){
if let someError = error{
machine.state = .Failure(someError)
} else{
machine.state = .Success(json)
}
}
}
@eastari
Copy link

eastari commented Jun 15, 2017

Ha sorry its work
let myClass = MyClass()
myClass.machine.state
myClass.machine.state = .Fetching
myClass.machine.state = .Ready
print(myClass.machine.state)
// .Ready, .Fetching
// Fetching

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment