SwiftUI Dynamic Predicate for FetchRequest

Andrew Ho
2 min readJan 9, 2021

I Learn faster by Example

A View cannot change its own FetchRequest after the view has been created. What if we want to modify the query string and update the display based on user input?

This SwiftUI limitation causes a small challenge when coding search boxes and other dynamic queries. The example below shows how this can be done:

  1. A View cannot change its own FetchRequest, but it can change the FetchRequest of one of its sub-Views. Thus, use a sub-View to generate the FetchRequest:

struct AllUsers: View {

@State private var searchTerm: String = “”

var body: some View {

TextField(“first or last name”, text: $searchTerm) // this is the search box

listUsers(searchTerm: searchTerm) // FetchRequest is in this sub-view

} // end view

} // end struct

2. In listUsers, use the searchTerm via init() to generate the FetchRequest and show the results:

struct listUsers: View {

private var fetchRequest: FetchRequest<Person>

init(searchTerm: String) {

fetchRequest = FetchRequest<Person>(entity: Person.entity(),

sortDescriptors: [],

predicate: NSPredicate(format: “(name CONTAINS[c] %@)”, searchTerm))

} // end init

var body: some View {

List(fetchedRequest.wrappedValue, id:\self) {person in

Text(person.name)

}

} // end view

} // end struct

How this works

When user types the search term into the TextField, each keystroke changes the State variable, searchTerm. Each time searchTerm is changed, the new version of searchTerm gets sent to listUsers, causing the predicate to update and the list of users to be updated.

--

--