I just started playing with the new property wrappers and I have a question regarding ObservedResults. Let’s say I have a collection of items and I want to display only a subset of it:
@ObservedResults(Item.self, filter: NSPredicate(format: "lastName begins with A")) var itemList
Later I would like to further filter that subset using a search field:
.onChange(of: searchText, perform: { searchString in itemList.filter = NSPredicate(format: "firstName begins with %@", searchString) })
Everything is working as expected but, when I clear the search field, I get back all the items without any filter (all the Item records from realm). And if, for any reason, SwiftUI re-renders the view, then I get the items properly filtered.
The comment within the ObservedResults implementation says:
A base value to reset the state of the query if a user reassigns the filter or sortDescriptor
value = try! Realm(configuration: configuration ?? Realm.Configuration.defaultConfiguration).objects(ResultType.self)
That means whenever the filter or the sort descriptor is changed, all the items are received, right?
Is there any way to have returned only the items as they were queried in the beginning?
Could you send us a small, self contained view/views that shows a good use case for this? I intentionally didn’t allow for sub filtering when designing the feature.
@ObservedResults(T.self, filter: NSPredicate(format: "documentDate BETWEEN {startDate, endDate}")) var results
let rowView: (T) -> RowView
let detailView: (T) -> DetailView
@State var selectedRow: T?
@State var searchText: String = ""
init(@ViewBuilder rowView: @escaping (T) -> RowView, @ViewBuilder detailView: @escaping (T) -> DetailView) {
self.rowView = rowView
self.detailView = detailView
}
var body: some View {
List(selection: $selectedRow) {
ForEach(results) { row in
rowView(row)
.tag(row)
}
}
.frame(minWidth: 300)
.listStyle(InsetListStyle())
.toolbar {
SearchField(searchText: $searchText)
.frame(minWidth: 150, idealWidth: 200, maxWidth: .infinity)
Spacer()
Button(action: { }, label: { Image("plus") })
}
.onChange(of: searchText, perform: { searchString in
$results.filter = searchString.isEmpty ? nil : NSPredicate(format: "companyName BEGINS WITH %@", searchString)
})
}
}`
Let’s assume we have an invoicing app and we want to retrieve only the documents within a specific month/period. Then we can search for the documents belonging to a specific customer.
But, as long as I clear the search field, I get all the results from realm not only those within the date range specified in the predicate. And on next rendering the results are updated correctly. For example, if the app window becomes inactive the results are updated and filtered properly.
The same thing can be applied to sortDescriptor where we can have an initial sorting and then use a control to sort the results as we want. Like NSTableView sorting headers.