I have an entity called Car.
I have this @FetchRequest to list the cars.
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Car.name, ascending: true)],
animation: .default)
var dishes: FetchedResults<Car>
This works wonderfully but now I want to add a search bar to the view.
I know that @FetchRequest has this syntax
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Car.name, ascending: true)],
predicate: // WTH I put here?,
animation: .default)
var dishes: FetchedResults<Dish>
I have tried to create a function called buildPredicate, as this:
func buildPredicate() -> NSPredicate {
if searchText == "" {
return NSPredicate(value: true)
}
return NSPredicate(format: "name CONTAINS[cd] %@", searchText)
}
but this will not work because to run this function I need self to be created first and while XCode is compiling the code self was not created yet.
The same is true for a computed var.
I know there is a way that you need to be a rocket scientist to use, and I have used it before, using something like this
struct FetchedObjects<T, Content>: View where T : NSManagedObject, Content : View {
let content: ([T]) -> Content
var request: FetchRequest<T>
var results: FetchedResults<T>{ request.wrappedValue }
// MARK: - Lifecycle
init(
predicate: NSPredicate = NSPredicate(value: true),
sortDescriptors: [NSSortDescriptor] = [],
@ViewBuilder content: @escaping ([T]) -> Content
) {
self.content = content
self.request = FetchRequest(
entity: T.entity(),
sortDescriptors: sortDescriptors,
predicate: predicate
)
}
instead of FetchRequest but I am wondering if there is an easier way.
Is there a way to build a predicate for @FetchRequest that works?
CodePudding user response:
Use .onChange(of:)
for your search text variable to build your predicate and update the fetch request
.onChange(of: searchText) { search in
if search.isEmpty {
dishes.predicate = NSPredicate(value: true)
} else {
dishes.predicate = NSPredicate(format: "name CONTAINS[cd] %@", search)
}
}