I have a SwiftData class that I get with @Query private var items: [Item]
in a SwiftUI view. Then I pass it to a sub view that passes it to other sub views. What is the best way to pass the class around. I need to be able to modify it, and its properties (structs and classes) in the sub views. Should I use @Binding, @Bindable, @ObservableObject or something else?
Here is an example of how to pass the items
around to various subviews.
In essence, use a let items: [Item]
in the subviews that just display the
info. Use a @Bindable var item: Item
when you want to modify an item
property.
Use @Environment(\.modelContext) private var modelContext
to add (or delete)
an item
to SwiftData, that will update your array items: [Item]
.
You cannot add
or delete
an item
from the array items: [Item]
directly
(it is read only), you must use the context.
@Model
final class Item {
var name: String
init(name: String) {
self.name = name
}
}
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: Item.self)
}
}
struct ContentView: View {
@Query private var items: [Item]
var body: some View {
Layer1View(items: items)
}
}
struct Layer1View: View {
let items: [Item]
var body: some View {
Text("Layer1View items count: \(items.count)")
Layer2View(items: items)
}
}
struct Layer2View: View {
@Environment(\.modelContext) private var modelContext
let items: [Item]
var body: some View {
List(items) { item in
EditorView(item: item)
}
Button("Add item") {
let newItem = Item(name: "Mickey Mouse")
modelContext.insert(newItem)
}
}
}
struct EditorView: View {
@Bindable var item: Item
var body: some View {
TextField("", text: $item.name).border(.red)
}
}