🙆

【SwiftData】@Queryが付与された配列をListに渡し、rowContentで各要素のBindingを使用する方法

2025/01/25に公開

Summary

ListのrowContentで各要素のBindableを作成することでBindingを使用できます。ForEachのcontentでも同様に機能します。

List(items) { item in
    let item = Bindable(item)
    TextField("Name", text: item.name)
}
List(items) { item in
    @Bindable var item = item
    TextField("Name", text: $item.name)
}

Description

本記事に辿り着かれた方の多くは、@Stateのノリで@Queryが付与された配列を使おうとされたと思います。

@Stateが付与された配列は、下記のコードの$itemsのようにBindingを使用でき、RowContent内でも$item.nameのようにBindingが使用できます。しかし、@Queryが付与された配列は@Stateが付与された配列のようにBindingを取得することができません。

List($items) { $item in
    TextField("Name", text: $item.name)
}

@Queryが付与された配列をListに渡し、rowContentでBindingを使用する場合は、各要素のBindableを作成する必要があります。

Bindableの作成方法は、私の知る限り以下の二通りとなります。

let item = Bindable(item)
@Bindable var item = item

実際に使用した場合は、下記の通りとなります。

@Model final class Item {
    var name: String

    init(name: String) { self.name = name }
}

struct ContentView: View {
    @Query private var items: [Item]

    var body: some View {
        List(items) { item in
            let item = Bindable(item)
            TextField("Name", text: item.name)
        }

//        List(items) { item in
//            @Bindable var item = item
//            TextField("Name", text: $item.name)
//        }
    }
}

Discussion