Dynamic Predicates with Core Data in SwiftUI
Create a reusable generic SwiftUI view to wrap dynamic Core Data content
With the release of iOS 13 Beta 5, Apple gave developers a way forward with using Core Data with SwiftUI but provide little in the way of usage details:
NSManagedObject
now conforms toObservableObject
. The new@FetchRequest
property wrapper can drive views from the results of a fetch request, andmanagedObjectContext
is now included in the environment. (50280673)
While this change was welcomed, it wasn’t clear (after playing around with these new APIs for a bit) how one was supposed to fetch anything other than a predetermined set of data in your SwiftUI view.
The problem in a nutshell:
How do we dynamically change the NSPredicate in the above example without using self
?
The answer is to wrap the fetch request in another view and pass the predicate down to that view!
We can create a containing view for the fetch request and initialize the containing view with the predicate like so:
But we can do better. What if you want to reuse this view in multiple lists in your application?
The answer is to build a wrapper view with Swift generics!
TL;DR — Just show me the codes:
The above code uses Swift generics and @ViewBuilder
to create a reusable SwiftUI component for any fetched objects.
Lets implement this in our previous example and create a list of Students:
We now have a way to dynamically replace the predicate when the button action is fired. And because SwiftUI will redraw our view’s body when the @State
property is changed, our list will update!
That’s it! Go forth and fetch data…