I have published two articles covering how to use the .searchable modifier effectively with Core Data.
Apple has introduced a new framework named SwiftData with the Beta version of iOS 17. I have been monitoring it and writing some sample programs with it, but until iOS 17 Beta 8, it had too many problems to be seriously considered. With this Beta version, I found SwiftData to be a viable framework and I have converted a couple of applications from CoreData to SwiftData successfully.
I will publish an article on how to do this conversion, but just to complete our series on the use of .searchable, let us proceed. It turns out to be much simpler than the Core Data case. Here is what the code for the data object looks like:
The data to be persisted (in this case a class named Entry) is wrapped with the @Model macro to declare that SwiftData has to persist it. The rest is quite simple, you declare variables as you would in memory and SwiftData takes care of it. The storage is also taken care of by SwiftData, but we have to declare which objects we want to persist. We do it in the main program, but we could also do it in the relevant views.
This statement in the main application file is used to declare that SwiftData should arrange storage for an object called Entry. By default it is an SQL file called default.sql, but it is possible to use other alternatives.
Let us look at the list view that does the filtering.
Note that the environment variable that typically declared the ViewContext that CoreData uses to manage the transition between the memory is now declaring the ModelContext which does the same thing for SwiftData. The @FetchRequest macro is converted to a @Query macro for SwiftData and the resulting variable is an array in the right type, rather than a complex FetchedResults structure which is more difficult to process. Now let us check how the List looks like.
The filtering will be done by the use of the filter modifier that filters the collection (entries) based on the boolean condition in the closure. I had to use a conditional statement, since the filter did not take care of an empty filter case. The contains functions returns false when the parameter is an empty string, whereas I would expect any string to contain an empty string. Thus the need to separate that case.
The use of the .searchable modifier is simple, since it uses the binding to the filter variable.
One thing I did not mention is that you do not need to explicitly use the save function since SwiftData takes care of the right moment to save. So we just insert any new object to the modelContext, whereas updating is taken care automatically.
This is my first take on this with a Beta version of the software, but up to now I’m quite happy with SwiftData.