Skip to content

Instantly share code, notes, and snippets.

@esphynox
Created March 10, 2019 17:19
Show Gist options
  • Save esphynox/82c8efb98c6e0b9abf16290fc960cb8e to your computer and use it in GitHub Desktop.
Save esphynox/82c8efb98c6e0b9abf16290fc960cb8e to your computer and use it in GitHub Desktop.
public class AsyncOperation: Operation {
@objc enum State: Int {
case ready
case executing
case finished
}
private let stateQueue = DispatchQueue(label: "\(Bundle.main.bundleIdentifier!).AsyncOperation.state", attributes: .concurrent)
private var _state: State = .ready
@objc dynamic var state: State {
get {
return stateQueue.sync {
_state
}
}
set {
stateQueue.sync(flags: .barrier) {
_state = newValue
}
}
}
open override var isReady: Bool {
return state == .ready && super.isReady
}
public final override var isExecuting: Bool {
return state == .executing
}
public final override var isFinished: Bool {
return state == .finished
}
open override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
if ["isReady", "isFinished", "isExecuting"].contains(key) {
return [#keyPath(state)]
}
return super.keyPathsForValuesAffectingValue(forKey: key)
}
public final override func start() {
if isCancelled {
finish()
return
}
state = .executing
main()
}
open override func main() {
fatalError("Subclasses must implement `main`.")
}
public final func finish() {
if isExecuting {
state = .finished
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment