When I enumerate an array of objects with ForEach, I often wonder how I use the array. For example, I have the following lines of code.
import SwiftUI
struct ContentView: View {
@State var checkItems: [CheckItem] = [
.init("Susan"),
.init("Meagan"),
.init("Daniel")
]
var body: some View {
List() {
ForEach(0..<checkItems.count, id: \.self) { index in
HStack {
Image(systemName: !checkItems[index].selected ? "circle" : "checkmark.circle.fill")
.resizable()
.scaledToFit()
.frame(height: 24)
.foregroundColor(!checkItems[index].selected ? .gray : .blue)
.onTapGesture {
checkItems[index].selected.toggle()
}
Text(checkItems[index].name)
}
}
}
}
}
struct CheckItem: Identifiable, Hashable {
var id = UUID()
var selected: Bool
var name: String
init(_ name: String) {
self.selected = false
self.name = name
}
}
The code works as shown in the following image.
In the following lines of code, I'm enumerating the same array in a slightly different fashion.
struct ContentView: View {
@State var checkItems: [CheckItem] = [
.init("Susan"),
.init("Meagan"),
.init("Daniel")
]
var body: some View {
List() {
ForEach(checkItems, id: \.id) { item in
HStack {
Image(systemName: !item.selected ? "circle" : "checkmark.circle.fill")
.resizable()
.scaledToFit()
.frame(height: 24)
.foregroundColor(!item.selected ? .gray : .blue)
.onTapGesture {
//item.selected.toggle() // Cannot use mutating member on immutable value: 'item' is a 'let' constant
}
Text(item.name)
}
}
}
}
}
And I get an error in the line inside the onTapGesture guy. I wonder why the first section of code works and why second section doesn't? Muchos thankos.
With the first method you are changing the checkItems
array directly using the index and all works well, but
using an index is not a recommended way.
To achieve the same with the second (preferred) method, you need to have a binding
for the item
to be able to change it.
To have that, use
ForEach($checkItems) { $item in ....}