Skip to content

Instantly share code, notes, and snippets.

@nvh nvh/DataSourceState.swift
Last active Oct 28, 2017

Embed
What would you like to do?
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
}
}
}
@racer1988

This comment has been minimized.

Copy link

racer1988 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
You can’t perform that action at this time.