Devlog: December 16, 2022
Search
Today I actually got to the UI. How exciting! I wanted to start with search, because I’ve never really done anything like that in SwiftUI before. I think it’s pretty straightforward.
When the search sheet initially loads, I populate it with some current popular movies (according to TMDb.) Then, as the user searches, I hit search endpoint and display those results. I was pretty surprised that .searchable
does not have a built in way to debounce or throttle the event. So I made my own workaround with Combine.
The first thing I tried was adding a debounce to the @State
publisher for the query.
struct Search: View {
@State private var query = ""
var body: some View {
NavigationStack {
List(searchResults) { media in
...
}
.searchable(text: $query.value)
}
.onReceive(query.publisher.debounce(for: 0.3, scheduler: DispatchQueue.main)) { query in
// Use the API to search and set results
}
}
}
This did not work for some reason. One day, I should understand why, but I don’t now. I thought you could subscribe to the state publisher?
The solution seemed to be to create an ObservableObject
to hold the query.
struct Search: View {
private class Query: ObservableObject {
@Published var value = ""
}
@StateObject private var query = Query()
var body: some View {
NavigationStack {
List(searchResults) { media in
...
}
.searchable(text: $query.value)
}
.onReceive(query.$value.debounce(for: 0.3, scheduler: DispatchQueue.main)) { query in
// Use the API to search and set results
}
}
}
A little overhead that seems unnecessary, but it works.