SwiftUI - does ForEach have a endIndex or lastindex?

Viewed 4616

I'm using ForEach to create a loop. However, I want to render a Rectangle conditionally depending upon the count of the loop. For example, don't render the rectangle if the last loop iteration.

What's the correct syntax for this?

I'm looking for something like this (non working pseudo-code)

ForEach(arrayOfThings, id: \.title) { thing in
    // Stuff that happens on every iteration of loop

    // Conditional section
    if (thing.endIndex-1) {
        Rectangle()
        .frame(width: 100, height: 1, alignment: .bottom)
        .foregroundColor(Color("666666"))
    }
}

I am aware there are things like for (offset, element) in array.enumerated() { } but you can't use them in views. I wondered if there is a convenience feature in ForEach to solve this need?

Currently I am doing this to workaround:

ForEach(0..<arrayOfThings.count) { i in
    // Stuff that happens on every iteration of loop

    // Conditional section
    if (i = self.arrayOfThings.count-1) {
        Rectangle()
        .frame(width: 100, height: 1, alignment: .bottom)
        .foregroundColor(Color("666666"))
    }
}
2 Answers

If your arrayOfThings is Equatable you could do

ForEach(arrayOfThings, id: \.title) { thing in
    if thing == arrayOfThings.last {
        // do something
    }
}

Which is more readable than checking index vs count in my opinion.

To know if it is the last element, you can just test if the KeyPath used as id is the same for last element and the current element.

Note that the id parameter is ensured to be unique (at runtime) and Equatable. Therefore, you cannot have any problems regarding duplicated elements or missing equality, like you could by using the element directly even if it is not used as id.

ForEach(myArray, id: \.someProperty) { element in
    if element.someProperty == myArray.last?.someProperty {
        // do something with the last element
    }
}

or in case you use an Identifiable element directly or use id: \.self:

ForEach(myArray) { element in
    if element == myArray.last {
        // do something with the last element
    }
}
Related