- Blog/
Simple SwiftData
I spent the past week updating my Swift code to the latest and greatest. In some cases it didn’t simplify much ( Observable), but I was able to remove a bunch of SQLite.swift code and replace it with just a few lines of SwiftData.
That code implemented the favorite feature in Talk Dim Sum, where you mark your favorite dishes and see only those in a separate view. Whereas before I stored the IDs of the favorited dishes in a table and wrote functions to insert, search for, and delete those entries, with SwiftData I defined a very simple persistent model containing that ID.
@Model
class Favorite {
@Attribute(.unique) var id: String
init(dish: Item) {
self.id = dish.id
}
}
Then add a modelContainer in the main view of the app that contains favorites.
var body: some Scene {
WindowGroup {
AppView()
.modelContainer(for: [
Favorite.self
])
.environment(dimsum)
.environment(places)
.environment(tts)
.environment(stt)
.environment(router)
}
}
To favorite a dish, just perform the insert on an environment object.
struct FavoriteButton: View {
@Environment(\.modelContext) private var context
let dish: Item
var body: some View {
ActionButton("dish.favorite", "heart") {
context.insert(Favorite(dish: dish))
}
}
}
To delete, access the stored favorites using @Query, and once I’ve found the one that matches the dish I want to unfavorite, call delete on the environment object.
struct RemoveFavoriteButton: View {
@Environment(\.modelContext) private var context
@Query() var faves: [Favorite]
let dish: Item
var body: some View {
ActionButton("dish.unfavorite", "heart.fill") {
let found = faves.filter { $0.id == dish.id }
context.delete(found[0])
}
}
}
And to display the list of favorites, just use that @Query and map the Favorites back to dishes (here I do some filtering to remove any obsolete IDs, as it’s possible for dishes to be removed or have their IDs changed).
struct FavoritesCollectionView: View {
@Environment(DimSum.self) var dimsum: DimSum
@Query() var faves: [Favorite]
var body: some View {
DishCollectionView(dishes: faves.filter({dimsum.isDish($0.id)}).map { dimsum[$0.id]! })
}
}