I know there have been I would say similar questions, but none of them fits my case -> see my already tried attempts below.
So what I'm trying to do is make a advanced searchBar. Therefore, everytime the searchParam changed, I need to execute code to check whether my TableViewItems (Array) match the criteria -> filter.
When smo. for example types 3 characters, my code checks this string. But this will take a while to get all results.
The Problem: When smo. then types the 4th character, I want to stop the previous execution and start a new one with the string of 4.
My Attempts:
Using DispatchWorkItem:
The problem here is that it only changes a Boolean and it take 10sec+ for the code to recognize that it changed. Works if I execute it
.sync
instead of.async
, but it freezes the app for more than 10secUsing DispatchQueue:
Can't be stopped, only paused -> so will remain in memory -> will spam memory
Checking Boolean in every
for loop
:Same as with DispatchWorkItem, will take 10+ sec to recognize a change
Current Code: (not very important)
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.stop = true
if people != nil {
if searchText.isEmpty {
searchedPeople = people
self.stop = false
} else {
self.searchedPeople = []
self.tableView.reloadData()
workItem = DispatchWorkItem(qos: .userInitiated, flags: []) {
outter: for i in 0...searchText.count - 1 {
if self.stop { self.stop = false;break outter } //
if i == 0 {
inner: for person in self.people! {
if self.stop { self.stop = false;break outter } //
let name = (person.Vorname != nil ? person.Vorname! + " " : "") + (person.Nachname ?? "")
if name.lowercased().contains(searchText.lowercased()) {
print("Found: \(name), \(searchText), Exact Match")
self.searchedPeople?.append(person);DispatchQueue.main.async { self.tableView.reloadData()}; continue inner
}
}
} else {
let firstP = searchText.prefix(i+1)
let lastP = searchText.suffix(searchText.count - i + 1)
inner2: for person in self.people! {
if self.stop { self.stop = false;break outter } //
let name = (person.Vorname != nil ? person.Vorname! + " " : "") + (person.Nachname ?? "")
if name.lowercased().contains(firstP.lowercased()) && (name.lowercased().contains(lastP.lowercased())) {
print("Found: \(name), \(searchText), First: \(firstP), Last: \(lastP)")
self.searchedPeople?.append(person)
DispatchQueue.main.async { self.tableView.reloadData()}
continue inner2
}
}
}
}
}
//execute
DispatchQueue.async(execute: workItem)
}
}
}