'SwiftUI, core data and search bar freezes when changing predicate [duplicate]

I'm trying to filter Core Data by changing the predicate when typing in the search bar, but doing so causes the app to freeze. At first I thought that the problem was in the search bar, but after several tests I realized that when changing the predicate the application freezes.

To try to illustrate what happens: you start typing in the bar and the results are displayed, they change as you type, which is correct. When tapping "Cancel" next to the bar, it sometimes works fine, the results are displayed as expected but most of the time the app to freeze.

If the predicate is exactly the same, the app does NOT freeze, it works fine, but it's not the case.

This is the code causing the problem:

.searchable(text: $searchText)
.onChange(of: searchText) { searchText in
    if !searchText.isEmpty  {
        data.nsPredicate = NSPredicate(format: "business == %@ && title CONTAINS[cd] %@" , business, searchText)
    } else {
        data.nsPredicate = NSPredicate(format: "business == %@", business)
    }
}

This code, while somewhat silly, demonstrates that if I don't change the predicate the problem doesn't show up.

.searchable(text: $searchText)
.onChange(of: searchText) { searchText in
    if !searchText.isEmpty  {
        data.nsPredicate = NSPredicate(format: "business == %@ && title CONTAINS[cd] %@" , business, searchText)
    } else {
        data.nsPredicate = NSPredicate(format: "business == %@ && title CONTAINS[cd] %@" , business, searchText)
    }
}

When freezing occurs, no error is displayed, just freezes, it happens on the simulator and on a real device.

Any ideas? Thanks!

Working code:

Finally got a solution as commented by lorem ipsum.

@State private var searchText = ""
var query: Binding<String> {
    Binding {
        searchText
    } set: { newValue in
        searchText = newValue
        datos.nsPredicate = newValue.isEmpty
        ? NSPredicate(format: "business == %@", business)
        : NSPredicate(format: "business == %@ && title CONTAINS[cd] %@" , business, newValue)
    }
}

var body: some View {

..........
..........

  .searchable(text: query)

}

Source: Apple's setup



Solution 1:[1]

You need to remove the onChange and pass the search text into your View that creates the FetchRequest, e.g.

SearchView(searchText)
private var fetchRequest: FetchRequest<Item>
private var items: FetchedResults<Item> {
    fetchRequest.wrappedValue
}

init(_ searchText: String) {
    fetchRequest = FetchRequest( // supply a NSPredicate using searchText
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1