I have a class with async methods. All the methods are the simplest:
class SomeClass {
func someFunc(params: SomeParams, completion: ((SomeResult) -> ())?) {
... //some code where completion is called asynchronously, not only with DispatchQueue.async
}
...//other methods
}
Now I need to add a possibility to cancel such these tasks but SomeClass
is not responsible for it so such code should be placed into another class outside SomeClass
. They recommend to use DispatchWorkItem
but how wrap such async calls into it correctly?
Note: there are questions and answers how to replace DispatchQueue.global().async
with DispatchWorkItem
, not about wrapping existing tasks
I know you’ve solved your problem already, but for the sake of future readers and in answer to the titular question whether you can “Wrap async task into
DispatchWorkItem
in Swift to make it cancellable?”, the answer is that, no, simply wrapping it inside aDispatchWorkItem
is generally not sufficient. As the documentation tells us (emphasis added):If you
cancel
aDispatchWorkItem
that you have already started, it merely setsisCancelled
property of thatDispatchWorkItem
that you could check within some computationally intensive routine. But for many asynchronous tasks (like network requests), that would be of limited utility.Worse,
DispatchWorkItem
is not well suited to wrap a task that is, itself, asynchronous. TheDispatchWorkItem
will generally finish the work item as soon as the asynchronous task has been launched, not waiting for it to complete (unless you do something kludgy and brittle, like using semaphores; so much so that it would best be considered an anti-pattern).You really need to incorporate the cancelation logic within
someFunc
. Historically, we often reached forOperation
subclasses (build upon the GCD framework) because we can then overridecancel
to trigger the cancelation of the asynchronous task. Or nowadays we might reach for the automatic cancelation propagation offered by Swift concurrency’sasync
-await
. Or, you appear to have achieved this with Combine.So, bottom line, it depends upon what
someFunc
was doing, butDispatchWorkItem
is often of limited utility, despite its (very basic) cancelation support.