I need to filter my model data with a search bar. I added the .searchable()
property and when the search text changes I filter my objects with fuzzy matching. This takes too much time and the app lags when writing into the search box. So I want to do the searching asynchronously so that the app doesn't freeze.
I tried to do it with the onChange(of:)
property and then I create a Task
that runs the async function because the onChange()
property doesn't allow async functions by themselves. But the app still lags.
Here is a code example of how I tried doing it:
import SwiftUI
import Fuse
struct SearchView: View {
@EnvironmentObject var modelData: ModelData
@State var searchText = ""
@State var searchResults: [Item] = []
@State var searchTask: Task<(), Never>? = nil
let fuseSearch = Fuse()
var body: some View {
// Show search results
}
.searchable(text: $searchText)
.onChange(of: searchText) { newQuery in
// Cancel if still searching
searchTask?.cancel()
searchTask = Task {
searchResults = await fuzzyMatch(items: modelData.items, searchText: newQuery)
}
}
func fuzzyMatch(items: [Item], searchText: String) async -> [Item] {
filteredItems = items.filter {
(fuseSearch.search(searchText, in: $0.name)?.score ?? 1) < 0.25
}
return filteredItems
}
}
I would really appreciate some help.