mesqueeb/swiftdatasugar
```
Sample Project: SwiftDataTodoList
A point of reference on how to implement CRUD via SwiftData on all Apple platforms.
Features of this proof of concept:
- Writing uses a background thread (uses the
@ModelActormacro) - Reading uses MainActor thread (uses SwiftUI's
@Querymacro) - Migration setup with unit testing
- Full Multi-platform support
1. Writing data
- Writing data to the SwiftData models is done on a background thread
- An
actorthat conforms toModelActorhas been set up with CRUD-like methods to easily write data to the model - This actor is called
DbCollection - Instantiating
DbCollectionmust be done on@MainActorto prevent an issue where writing data isn't reactive in SwiftUI. (see detailed explanation at A New Issue: The View Does Not Refresh After Data Update, an issue I've reported to Fatbobman and prompted him to write an article on) DbCollectioncan be used for multiple models- in this app the usage of
DbCollectionis showcased for aTodomodel
// example instantiating multiple collections in the `@main` swift file
@MainActor public let dbTodos = DbCollection<TodoItem>(modelContainer: modelContainer)
@MainActor public let dbUsers = DbCollection<User>(modelContainer: modelContainer)2. Reading data
- Reading data from the SwiftData models is done on the MainActor thread
- SwiftUI's
@Querycan be used for simple views that need to query data without dynamic requirements - The usage of
@Queryis wrapped in new view calledDbQuerywhere you can pass a dynamic predicate and sortBy instances that queries data - in this app the usage of
DbQueryis showcased for a list that can be filtered and sorted dynamically
DbQuery(predicate: activePredicate, sortBy: activeSort) { items in
ForEach(items, id: \.id) { item in
TodoListItemView(item: item)
.id(item.id) // Use ID for List reordering and animations
}
}
}3. Migration setup with unit testing
- Custom Migrations in SwiftData, which are hard to get right, are showcased in this app with 3 versions and 2 migrations
- The latest schema has all of its structs and models type aliased for easier use throughout the codebase
- Only data crucial to migrations is scoped inside of the versioned schema, other usefull methods and convenience initialisers are extended only on the latest schema
- Actual migration logic neatly organised per-version: it bundles just the logic to upgrade to the relevant version in the same file as that version's schema
- The final combined migration plan combines each migration step per version
- Full unit testing in place of each migration phase (with modern Swift Testing) to give confidence a latest migration will not crash your user's apps on launch
- The unit testing showcases exaclty how to test migrations in SwiftData
4. Multi-Platform Support
- All code used in this proof of concept is compatible with all Apple platforms
Package Metadata
Repository: mesqueeb/swiftdatasugar
Default branch: main
README: README.md