Doing this code-along, I'm trying to verify what little understanding I have of SwiftData by making a bare bones example.
This works:
import SwiftUI
@main
struct WWPDApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
// this makes modelContext available in the app
.modelContainer(for: Memo.self)
}
}
struct ContentView: View {
// for getting swiftdata
@Query private var memos: [Memo]
// for setting swiftdata
@Environment(\.modelContext) var modelContext
var body: some View {
VStack {
Button("ADD MEMO") {
modelContext.insert(Memo(name: "new memo"))
}
List(memos) {memo in
Text(memo.name)
}
}
.padding()
}
}
// Putting "@Model" here makes this class work with swift data
@Model
final class Memo {
var id: UUID
var name: String
init(id: UUID = UUID(), name: String) {
self.id = id
self.name = name
}
}
That works and verifies that we can add new objects and they are saved.
However, I would like to verify and understand the editting/binding aspect.
I understand that the modelContext is only used for inserting a new object. For editting an existing object, we are to rely on two way bindings with an object contained in the queried array(?)...
So I tried this:
struct ContentView: View {
// for getting swiftdata
@Query private var memos: [Memo]
// for setting swiftdata
@Environment(\.modelContext) var modelContext
var body: some View {
// need to put some kind of @Bindable thingy here
VStack {
Button("ADD MEMO") {
modelContext.insert(Memo(name: "new memo"))
}
List(memos) {memo in
TextField("this doesn't work", text: memo.$name)
}
}
.padding()
}
}
The @Model final class Memo ...
enables change tracking for the class by adding conformance to the Observable
protocol. So when you want a binding eg for memo.name
you could use a @Bindable
as shown in the example code.
struct ContentView: View {
// for getting swiftdata
@Query private var memos: [Memo]
// for setting swiftdata
@Environment(\.modelContext) var modelContext
var body: some View {
VStack {
Button("ADD MEMO") {
modelContext.insert(Memo(name: "new memo"))
}
List(memos) { memo in
@Bindable var memo = memo // <--- here
TextField("this works", text: $memo.name) // <--- here
}
}
.padding()
}
}