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