Operation
and OperationQueue
are great and useful Foundation framework tools for asynchronous tasks. One thing puzzled me though: How can I run code after all my queue operations finish? The simple answer is: use dependencies between operations in the queue (unique feature of Operation). It's just 5 lines of code solution.
Operation dependency trick
with Swift it is just easy to implement as this:
extension Array where Element: Operation {
/// Execute block after all operations from the array.
func onFinish(_ block: @escaping () -> Void) {
let doneOperation = BlockOperation(block: block)
self.forEach { [unowned doneOperation] in doneOperation.addDependency($0) }
OperationQueue().addOperation(doneOperation)
}
}
what happened? new BlockOperation
depends on all operations from the array, as such will be executed at the end, after all operations finish.
Interesting note: dependency may be set between different queues 👍
Usage
[operation1, operation2].onFinish {
print("all done")
}
or directly with OperationQueue
operationQueue.operations.onFinish {
print("blocks done")
}
neat!
Update: Swift 5.x introduced OperationQueue.addBarrierBlock()
that may be used to schedule a closure to execute after all previously scheduled tasks. Tasks scheduled after this point will execute after barrier block finish execution.
Grand Central Dispatch trick
Of course I use GCD (import Dispatch
) a lot (a way more often than Operation
) because I found it convenient and fit to most of the cases. To build the same functionality I'd create DispatchGroup
and use it to notify when all tasks completed, like here:
let queue = DispatchQueue(label: "my queue", attributes: .concurrent)
let group = DispatchGroup()
// called when all blocks associated with the
// dispatch group have completed.
group.notify(queue: .main) {
print("done")
}
// dispatch asynchronous blocks
for idx in 0..<5 {
queue.async(group: group) {
print(idx)
}
}
Not that neat as Operation
.
Conclusion
Seriously I love 💓 this simple, small features of Swift that makes daily tasks so simple, yet powerful. If you work with Operations you may find it useful in daily hacking.
5 Apr 2020: Updated to Swift 5.2