Background
I'm implementing a search. Each search query results in one DispatchWorkItem which is then queued for execution. As the user can trigger a new search faster than the previous one can be completed, I'd like to cancel the previous one as soon as I receive a new one.
This is my current setup:
var currentSearchJob: DispatchWorkItem?
let searchJobQueue = DispatchQueue(label: QUEUE_KEY)
func updateSearchResults(for searchController: UISearchController) {
let queryString = searchController.searchBar.text?.lowercased() ?? ""
// if there is already an (older) search job running, cancel it
currentSearchJob?.cancel()
// create a new search job
currentSearchJob = DispatchWorkItem() {
self.filter(queryString: queryString)
}
// start the new job
searchJobQueue.async(execute: currentSearchJob!)
}
Problem
I understand that dispatchWorkItem.cancel()
doesn't kill the running task immediately. Instead, I need to check for dispatchWorkItem.isCancelled
manually. But how do I get the right dispatchWorkItem
object in this case?
If I were setting currentSearchJob
only once, I could simply access that attribute like done in this case. However, this isn't applicable here, because the attribute will be overriden before the filter()
method will be finished. How do I know which instance is actually running the code in which I want to check for dispatchWorkItem.isCancelled
?
Ideally, I'd like to provide the newly-created DispatchWorkItem
as an additional parameter to the filter()
method. But that's not possible, because I'll get a Variable used within its own initial value
error.
I'm new to Swift, so I hope I'm just missing something. Any help is appreciated very much!