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"))
}
}
ForEach in SwiftUI is a view struct in its own right, which means you can return it directly from your view body if you want. You provide it an array of items, and you may also need to tell SwiftUI how it can identify each of your items uniquely so it knows how to update them when values change.
It is just a variable. For-each cannot be used to initialize any array or Collection, because it loops over the current contents of the array or Collection, giving you each value one at a time. The variable in a for-each is not a proxy for an array or Collection reference.
It is not possible to use procedural looping mechanisms such as For and While loops to layout views in SwiftUI. The SwiftUI framework provides the ForEach struct to accomplish an alternative to repeatedly add views to a view.
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With