Skip to content

Instantly share code, notes, and snippets.

@nvh
Last active October 28, 2017 21:58
Show Gist options
  • Save nvh/1b09b32a335be28e47e8 to your computer and use it in GitHub Desktop.
Save nvh/1b09b32a335be28e47e8 to your computer and use it in GitHub Desktop.
Data loading state machine enum
enum DataSourceState<D,E> {
case Empty
case Loading(Box<D?>)
case Ready(Box<D>)
case Error(Box<E>,Box<D?>)
func toLoading() -> DataSourceState {
switch self {
case .Ready(let oldData):
let value: D? = oldData.value
return .Loading(Box(value))
default:
return .Loading(Box(nil))
}
}
func toError(error:E) -> DataSourceState {
switch self {
case .Loading(let oldData):
return .Error(Box(error),Box(oldData.value))
default:
assert(false, "Invalid state transition to .Error from other than .Loading")
}
}
func toReady(data: D) -> DataSourceState {
switch self {
case .Loading:
return .Ready(Box(data))
default:
assert(false, "Invalid state transition to .Ready from other than .Loading")
}
}
var data: D? {
switch self {
case .Empty:
return nil
case .Ready(let data):
return data.value
case .Loading(let data):
return data.value
case .Error(_, let data):
return data.value
}
}
var error: E? {
switch self {
case .Error(let error, _):
return error.value
default:
return nil
}
}
}
@pappalar
Copy link

pappalar commented Jun 1, 2017

Hi! I saw this Gist on http://nvh.github.io/2015/02/13/state-machine-inside-swift-enum.html

I really like the idea of using function to handle the validity of state changes.
However I have a question for API design.

With this API I cannot forbid somebody else using my state (for example as part of a Framework) the wrong way.

If the developer changes always state like:

self.state = state.toLoading()

then every state change works fine.

however this does not forbid them to do

self.state = .loading

and removing the checks on state validity.
Do you have any ideas on how to mask it for the enum?

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