Last active
March 31, 2020 16:52
-
-
Save jeffery812/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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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