here is a simple project using a swift data where I saved over 75000 airports.
I'm trying to find the best and faster way to search on this db, right now the search works but it is very very slow and the UI frozen while searching.
How can I optimize the search?
import SwiftUI
import SwiftData
import Combine
struct Airports: View {
@StateObject var ds = DebounceState(initialValue: "", delay: 1)
@Environment(\.modelContext) private var mc
@Query var apt: [Airport]
var body: some View {
List{
ForEach(ds.filterApt){ apt in
Text(apt.icao)
}
}
.searchable(text: $ds.searchText, prompt: "Search apt")
.onChange(of: ds.debouncedValue) { oldValue, newValue in
ds.searchAirport(newValue, mc: mc)
}
}
}
class DebounceState<Value>: ObservableObject {
@Published var searchText : Value
@Published var debouncedValue : Value
@Published var filterApt : [Airport] = []
var subscriber : AnyCancellable?
init(initialValue: Value, delay: Double) {
_searchText = Published(initialValue: initialValue)
_debouncedValue = Published(initialValue: initialValue)
subscriber = $searchText
.debounce(for: .seconds(delay), scheduler: RunLoop.main)
.assign(to: \.debouncedValue, on: self)
}
func searchAirport(_ airport: String, mc: ModelContext) {
let uairport = airport.uppercased() // cant find the way for predicate to be case insenitive
do {
let container = try ModelContainer(for: Airport.self)
let contex = ModelContext(container)
print("serach fo \(uairport)")
let filterPlane = FetchDescriptor<Airport>(
predicate: #Predicate { input in
input.icao.contains(uairport)
})
filterApt = try contex.fetch(filterPlane)
}catch {
fatalError("Fail search")
}
}
}
@Model
class Airport {
@Attribute(.unique) var id: UUID
var lastPicked : Date
var icao : String
init(id: UUID, lastPicked: Date, icao: String) {
self.id = id
self.lastPicked = lastPicked
self.icao = icao
}
static var all: FetchDescriptor<Airport> {
let sort = [SortDescriptor(\Airport.icao, order: .forward)]
var res = FetchDescriptor(sortBy: sort)
res.fetchLimit = 100
return res
}
}
Thanks