When using a ForEach View, I often pass \.self as the ID.
struct ContentView: View { let colors: [Color] = [.red, .green, .blue] var body: some View { VStack { ForEach(colors, id: \.self) { color in Text(color.description.capitalized) .padding() .background(color) } } } }
When each view created by ForEach is created or removed, it tells the views apart by their ID value so that only that part gets updated.
That's why you pass the id argument.
public init(_ data: Data, id: KeyPath<Data.Element, ID>, @ViewBuilder content: @escaping (Data.Element) -> Content)
The id argument you pass to the ForEach view is passed as a keyPath, and the value taken from the data through that keyPath
is decided as the unique identifier so that each view can be told apart.
So in the example above, since we passed \.self, which omits \Color.self, the unique identifier of each view becomes .red, .green, .blue in order.
Then what should we do if the elements of the data are the same?
For example, when the colors array looks like this.
let colors: [Color] = [.red, .red, .blue]
A Stack Overflow answer recommends wrapping it in a struct that conforms to the Identifiable protocol.
Create a struct like the following and generate a unique identifier with the UUID() function.
struct MyColor: Identifiable { var id = UUID() var color: Color }
Then pass the keyPath as .id like this so that each view becomes unique.
struct ContentView: View { let colors: [MyColor] = [.init(color: .red), .init(color: .red), .init(color: .blue)] var body: some View { VStack { ForEach(colors, id: \.id) { myColor in Text(myColor.color.description.capitalized) .padding() .background(myColor.color) } } } }