8

Since Swift 5.5 we could create SwiftUI lists with bindings like this (e.g. see this answer):

class Item {
    // ...
    var isOn: Bool
}

struct ContentView: View {
    @State private var items: [Item] = []
    var body: some View {
        NavigationView {
            List {
                ForEach($items) { $item in     // <--- list binding
                    Toggle(isOn: $item.isOn) {
                        Text("Vibrate on Ring")
                    }
                }
            }
        }
    }
}

Now I want to do something similar with SwiftData but I get an error:

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]
    var body: some View {
        NavigationView {
            List {
                ForEach($items) { $item in //   <--- Cannot find '$items' in scope
    // ...

How can I render a list of SwiftData objects that allows inline editing of objects through bindings?

HangarRash
  • 7,314
  • 5
  • 5
  • 32
de.
  • 7,068
  • 3
  • 40
  • 69

3 Answers3

7

The easiest solution I found is to use @Bindable and to separate the Query macro and the Bindable into different views.

An example

struct ItemRow: View {
    @Bindable var item: Item
   
    var body: some View {
        HStack {
            Text(item.name)
            Toggle(isOn: $item.isOn) // Notice the $
        }
    }
}

Calling view

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]
    var body: some View {
        NavigationView {
            List {
                ForEach(items) { item in
                    ItemRow(item: item)
     //...
}
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
7

You can utilize the new Bindable, which has a subscript operator to wrap the underlying data into a binding variable:

ForEach(items) { item in
    Toggle(isOn: Bindable(item).isOn) { ... }
}
Ranoiaetep
  • 5,872
  • 1
  • 14
  • 39
0

Swift Bindable Structure can be used like the example given below.

import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]
    var body: some View {
        NavigationView {
            List {
                ForEach(items) { item in
                    Toggle(isOn: Bindable(item).isOn) {
                        Text("Vibrate on Ring")
                    }
                }
            }
        }
    }
}