Skip to content

Instantly share code, notes, and snippets.

@andrekandore
Last active August 18, 2017 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrekandore/f2539a74002d1255cfc3da58faf0f007 to your computer and use it in GitHub Desktop.
Save andrekandore/f2539a74002d1255cfc3da58faf0f007 to your computer and use it in GitHub Desktop.
Just an idea!
actor Downloader {
let mainActor : TheMainActor
var theList : [URL] = []
init(mainActor: TheMainActor) { self.mainActor = mainActor }
actor case .initialized, .ready {
actor func setList(list:[String]) -> self.ready? //can only call this from these 2 (initialized and ready) states
}
actor case .ready {
actor func start() -> self.downloading?
}
actor case .downloading, .finished
public var progress : Float
}
}
//If the state was explicit for such an actor, it makes it…
// - basically impossible to misuse it (from inside and outside)
// - eliminates a lot of boilerplate
// - only the actor itself can change its state explicitly
// - easier to attach handlers/observers to the actor upon state change (im thinking KVO, wiring up multiple actors etc)
// - more clear about the state to the reader and write of the code
// - reduces 'var soup' that a lot of classes become when state gets complex since each variable is tied to an explicit state just like an enum
// - its possible then to add preconditions (and maybe even automatic errors) for each state like…
actor case .finished {
precondition {
self is [.downloading, .canceled]
progress >= 1
}
}
actor case .ready {
precondition {
theList.count > 0
}
}
//How would you access and check state?
//Since each state could be returned as an optional, it might be something like this…
let aDownloader = Downloader(mainActor:UIActor)
//not even possible, since .start() doesn’t exist in the initial state
aDownloader.start()
//wont call start() because 'ready' returns nil (theList hasnt been set yet)
aDownloader.ready?.start()
//ok
aDownloader.initialized?.setList(list)
//you could also chain operations...
let download = try aDownloader.initialized?.setList(list)?.start() //ok
//check progress
let progress = download.progress
//or,,,
let progress = aDownloader.downloading?.progress
//wait until finished
let result = await downloading.finished
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment