I can't undertand how to use @Binding
in combination with ForEach
in SwiftUI. Let's say I want to create a list of Toggle
s from an array of booleans.
struct ContentView: View { @State private var boolArr = [false, false, true, true, false] var body: some View { List { ForEach(boolArr, id: \.self) { boolVal in Toggle(isOn: $boolVal) { Text("Is \(boolVal ? "On":"Off")") } } } } }
I don't know how to pass a binding to the bools inside the array to each Toggle
. The code here above gives this error:
Use of unresolved identifier '$boolVal'
And ok, this is fine to me (of course). I tried:
struct ContentView: View { @State private var boolArr = [false, false, true, true, false] var body: some View { List { ForEach($boolArr, id: \.self) { boolVal in Toggle(isOn: boolVal) { Text("Is \(boolVal ? "On":"Off")") } } } } }
This time the error is:
Referencing initializer 'init(_:id:content:)' on 'ForEach' requires that 'Binding' conform to 'Hashable'
Is there a way to solve this issue?
You can use something like the code below. Note that you will get a deprecated warning, but to address that, check this other answer: https://stackoverflow.com/a/57333200/7786555
import SwiftUI struct ContentView: View { @State private var boolArr = [false, false, true, true, false] var body: some View { List { ForEach(boolArr.indices) { idx in Toggle(isOn: self.$boolArr[idx]) { Text("boolVar = \(self.boolArr[idx] ? "ON":"OFF")") } } } } }
Most of the answers (including the @kontiki accepted answer) method cause the engine to rerender the entire UI on each change and Apple mentioned this as a bad practice at wwdc2021 (around time 7:40)
From this version of swift, you can use binding array elements directly by passing in the bindable item like:
⚠️ Note that Swift 5.5 is not supported on iOS 14 and below but at least check for the os version and don't continue the bad practice!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With