Skip to content

Instantly share code, notes, and snippets.

@zhihuitang
Last active March 31, 2020 16:52
Show Gist options
  • Save zhihuitang/950209397d4b343a723db9bf0082867d to your computer and use it in GitHub Desktop.
Save zhihuitang/950209397d4b343a723db9bf0082867d to your computer and use it in GitHub Desktop.
AsyncOperation: Wrap Asynchronous Function in Operation For synchronous tasks, you can create an Operation subclass by overriding the main() method. AsyncOperation is a custom subclass of Operation that handles state changes automatically. Then, to
class AsyncOperation: Operation {
enum State: String {
case Ready, Executing, Finished
fileprivate var keyPath: String {
return "is" + rawValue
}
}
var state = State.Ready {
willSet {
willChangeValue(forKey: newValue.keyPath)
willChangeValue(forKey: state.keyPath)
}
didSet {
didChangeValue(forKey: oldValue.keyPath)
didChangeValue(forKey: state.keyPath)
}
}
}
extension AsyncOperation {
// DONE: Operation Overrides
override var isReady: Bool {
return super.isReady && state == .Ready
}
override var isExecuting: Bool {
return state == .Executing
}
override var isFinished: Bool {
return state == .Finished
}
override var isAsynchronous: Bool {
return true
}
override func start() {
if isCancelled {
state = .Finished
return
}
main()
state = .Executing
}
override func cancel() {
state = .Finished
}
}
// How to use it
class SumOperation: AsyncOperation {
// DONE: Properties, init, main
let lhs: Int
let rhs: Int
var result: Int?
init(lhs: Int, rhs: Int) {
self.lhs = lhs
self.rhs = rhs
super.init()
}
override func main() {
asyncAdd_OpQ(lhs: lhs, rhs: rhs) { result in
self.result = result
self.state = .Finished
}
}
}
private let additionQueue = OperationQueue()
public func asyncAdd_OpQ(lhs: Int, rhs: Int, callback: @escaping (Int) -> ()) {
additionQueue.addOperation {
sleep(1)
callback(lhs + rhs)
}
}
let additionQueue = OperationQueue()
let input = [(1,5), (5,8), (6,1), (3,9), (6,12), (1,0)]
for (lhs, rhs) in input {
// DONE: Create SumOperation object
let operation = SumOperation(lhs: lhs, rhs: rhs)
operation.completionBlock = {
guard let result = operation.result else { return }
print("\(lhs) + \(rhs) = \(result)")
}
// DONE: Add SumOperation to additionQueue
additionQueue.addOperation(operation)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment