Overview
In order for this to work properly you need to have some unique id
witin your collection. This stated in the documentation.
Either the collection’s elements must conform to Identifiable or you need to provide an id parameter to the ForEach initializer.
Lets create some dummy data
import SwiftUI
struct Foo: Identifiable {
var id: UUID = UUID()
var name: String
}
let results = [Foo(name: "Example 1"), Foo(name: "Example 2")]
At this point lets see what happens when we enumerate on the list.
let enumeratedList = results.enumerated()
let b = enumeratedList.map({$0})
print(b)
/*
[
(offset: 0, element: Foo(id: 4E0F77DA-6276-425E-A697-55FDA7F42190, name: "Example 1")),
(offset: 1, element: Foo(id: B88C0865-9E90-47B4-899F-9231D8F585D2, name: "Example 2"))
]
*/
Array of Tuples
If you look at the results of b
we get an array of tuples that have the keys offset
and element
. The offset is unique because it’s the index position of that item and we can use that as an ID for the ForEach
.
In order to access the element of offset
we can use .0
. As that is the first element within that tuple.
// Example with an Array of Structs.
ForEach(results.enumerated().map({$0}), id:\.0) { index, item in
// ... you can pass in the index or item
}
// Example with Strings
ForEach(["baseball", "basketball", "hockey"].enumerated().map({$0}), id:\.0) { index, item in
// ... you can pass in the index or item
}
Conclusion
Using enumerated()
and map
will return us a collection of tuples. This can be used to then pass into the ForEach
for iterarting over this list.
This can solution can be fine for trying out some data in a collection, but I do suggesting converting the array of tuples into an array of structs. It will make your life much easier. Check out the “Conclusion” on how you could approach this at a blog post on this topic.