DEV Community

Liang Wang
Liang Wang

Posted on

Searchable in CoreData

When I finally got the data saved in Core Data and showed them in a list, I was looking for a way to make the list searchable, in hope that the list would dynamically update itself when user starts searching.

In the tutorial I was following, it was introducing me to write a whole new FetchRequest filtered list, which I found to be quite difficult to follow. But I know that I can make a normal List searchable by using the .searchable() modifier, can I use this for the fetchedResults<DataType>?

The answer is yes, after searching for a while, I found this great answer on StackOverflow, someone has exactly the same question as I did, and the answers was working like a charm.

The answer is here:

WWDC 2021 Bring Core Data Concurrency to Swift and SwiftUI has a great example of this right around minute 21:33

https://developer.apple.com/wwdc21/10017

struct ContentView: View {
    @FetchRequest(sortDescriptors: [SortDescriptor(\Quake.time, order: .reverse)])
    private var quakes: FetchedResults<Quake>

@State private var searchText = ""
    var query: Binding<String> {
        Binding {
            searchText
        } set: { newValue in
            searchText = newValue
            quakes.nsPredicate = newValue.isEmpty ? nil : NSPredicate(format: "place CONTAINS %@", newValue)
        }
    }
    var body: some View {
        List(quakes) { quake in
            QuakeRow(quake: quake)
        }
        .searchable(text: query)
    }
}
Enter fullscreen mode Exit fullscreen mode

The only thing we need to update here is the “place” in NSPredictate(format: “place CONTAINS %@”)

And if you have more than one predicate for your search, you can use the NSCompoundPredicate() like this, as provided in another answer on StackOverflow

let p1 = NSPredicate(format: "username = %@", "user")
let p2 = NSPredicate(format: "password = %@", "password")
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p1, p2])

Enter fullscreen mode Exit fullscreen mode

You can choose to use the logic operator and, or, not, in the NSCompoundPredicate, it is “and” in the example above.

Top comments (0)