Element and Index: Enumerated ForEach in Swift UI
Looping through an array of elements to display them in a list is a very common and, thus, quite straightforward task in SwiftUI. One might think accessing the index
of an elemen
should be just as simple.
But it's not… so let's discover it together.
To have the element
and index
available in our loop, we cannot just iterate over the Array
as is. Instead, we have to create an enumerated version of it to create an EnumeratedSequence
. Doing that, the compiler will reward us with the following warning:
Generic struct 'ForEach' requires that 'EnumeratedSequence<[String]>' conform to 'RandomAccessCollection'
To resolve this issue, we can simply cast the Sequence
back to an Array
like so:
Array(fruits.enumerated())
In case you are eager to learn more about, what's happening in detail when we convert our array to an EnumeratedSequence
and back, please find more information down below.
The final list example looks like the following:
struct EnumeratedListView: View {
var body: some View {
let fruits = ["Apple", "Orange", "Banana"]
List{
ForEach(Array(fruits.enumerated()), id: \.offset) { index, fruit in
Text("\(index): \(fruit)").tag(index)
}
}
}
}
I hope that helps you deal with that pesky problem and makes you sleep better at night.
Happy Coding!
XOXO, Christian 👨🏻💻
Enumerating an Array
The enumerated()
function is called on an array (or any other collection) and returns a sequence of tuples, where the first element of each tuple is the index of the corresponding element in the original array, and the second element is the value from the original array.
In the given example, when you call fruits.enumerated()
, it creates an enumerated sequence, with each tuple containing the index and the element from the original array. However, to use this enumerated sequence in the ForEach
view in SwiftUI, we need to convert it to an array. That's because ForEach
expects a data source that conforms to the RandomAccessCollection
protocol, which EnumeratedSequence
does not conform to.
By using Array(yourArray.enumerated())
, you convert the enumerated sequence back to an array of tuples, which conforms to the RandomAccessCollection
protocol. This allows you to use it as a data source for ForEach
without any issues. Inside the loop, you can then access both the index and the element for each item in the array.
The resulting array looks as follows:
[(0, "Apple"), (1, "Orange"), (2, "Banana")]