Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request refactors the SwiftUI demo application:
@Query
property wrapper that lets views automatically display an up-to-date state of the databaseThis work is entirely based on Core Data and SwiftUI by @davedelong. I highly recommend reading this article! Below I will pay tribute to this generous sharing of experience 🙂
Dave's has polished his laws of Core Data over the years. This paragraph of him pretty much resonates with me:
Indeed, support for
struct
is ready made in GRDB, thanks to its record protocols, and his advice about information hiding is pervasive in the Good Practices for Designing Record Types.Based on this common foundation, we can come back to Dave's take on Core Data and SwiftUI. He wrote:
🤩 What isn't to love in this roadmap?
The demo app already had an equivalent of
DataStore
, namedAppDatabase
, which is the object that handles all database mutations.Dave's goal is to design his
@Query
property wrapper so that it can update a SwiftUI view with the latest state of the database, as instructed byQueryable
andQueryFilter
. The design of those protocols matches Core Data's observation tool, NSFetchedResultsController, which track lists of managed objects.Since GRDB can observe any kind of database content (not only lists of records), this pull request also defines a
Queryable
protocol, but without constraining it to any particular record type:Dave's
QueryResults
has no GRDB equivalent, because we do not currently support lazy collections of many database rows.Applying
Queryable
in the demo app gives:Here is how the demo app can use
PlayerRequest
with the@Query
property wrapper:This is not as pretty as Dave's goal: his
@Query(.all)
is unmatched. But I did not find a way to tie the query type to the type of the tracked value, as Dave could do given the constraints of NSFetchedResultsController. GRDB has no "natural" fetched type, and no "natural" request type either: it tracks the results of functions that accept a database connection, and these functions can do and return anything.But this is not bad!
And now we get to the most sexy of Dave's ideas. He wrote:
This matches so well the use case of the demo app, which lets the user choose the ordering of the player list (by name or by score)!
His idea makes it very easy to toggle player ordering from the view: