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
DispatchWorkItemin Swift to make it cancellable?”, the answer is that, no, simply wrapping it inside aDispatchWorkItemis generally not sufficient. As the documentation tells us (emphasis added):If you
cancelaDispatchWorkItemthat you have already started, it merely setsisCancelledproperty of thatDispatchWorkItemthat you could check within some computationally intensive routine. But for many asynchronous tasks (like network requests), that would be of limited utility.Worse,
DispatchWorkItemis not well suited to wrap a task that is, itself, asynchronous. TheDispatchWorkItemwill 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 forOperationsubclasses (build upon the GCD framework) because we can then overridecancelto 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
someFuncwas doing, butDispatchWorkItemis often of limited utility, despite its (very basic) cancelation support.