I have a loop where I update a value that changes the view.
In this example I want the updates to happen one at a time so you see it ripple across the row, but they all happen at once.
struct AnimationQuestion: View {
@State var colors = "🟪🟨🟧🟦🟥🟫⬛️🟩⬜️".map { String($0) }
@State var reversedColors = "⬜️🟩⬛️🟫🟥🟦🟧🟨🟪".map { String($0) }
var body: some View {
VStack {
Spacer()
Button("Tap") {
let temp = colors
for i in 0 ..< colors.count {
withAnimation(.linear(duration: 4.0)) {
colors[i] = reversedColors[i]
}
}
reversedColors = temp
}
Spacer()
HStack {
ForEach(Array(colors.enumerated()), id: \.0) { index, color in
Text(color).tag(index)
}
}
Spacer()
}
}
}
struct QuestionPreview: PreviewProvider {
static var previews: some View {
AnimationQuestion()
}
}
I expected these lines to perform the animation sequentially (visibly):
withAnimation(.linear(duration: 4.0)) {
colors[i] = reversedColors[i]
}
>Solution :
You identify by index \.0, but indices do not change after reversing, so refresh is instant, instead you need to identify by color value \.1 (in this case they are unique).
Here is a fix
ForEach(Array(colors.enumerated()), id: \.1) { index, color in
Text(color).tag(index)
}
Tested with Xcode 13.3 / iOS 15.4
