List with ForEach Enumeration

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.

Accepted Reply

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 ....}
  • That is it. Thanks a lot.

Add a Comment

Replies

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 ....}
  • That is it. Thanks a lot.

Add a Comment