I am working on a project involving SwiftUI lists. One of my views contains a list with relatively complex list items. To reduce code complexity I have created a subview for each item, like this (Simplified but reproduces the problem):
import SwiftUI
struct SubView: View {
var val: String
var body: some View {
Text(val)
}
}
struct TestView: View {
@State var objects = ["A", "B", "C", "D", "E"]
var body: some View {
List(objects, id: \.self) { ob in
SubView(val: ob)
.onTapGesture {
objects.removeAll { $0 == ob }
}
}
.animation(.default, value: objects)
}
}
#Preview {
TestView()
}
This code works as intended, expect for the animations. When an item is clicked, the last item in the list fades (even if some other item is deleted) and then the list changes without animation to the correct list. This code, however, does work as intended:
import SwiftUI
struct TestView: View {
@State var objects = ["A", "B", "C", "D", "E"]
var body: some View {
List(objects, id: \.self) { ob in
Text(ob)
.onTapGesture {
objects.removeAll { $0 == ob }
}
}
.animation(.default, value: objects)
}
}
#Preview {
TestView()
}
These views are effectively the same, so I would expect them to both have functional animations, but the first does not. Why does this happen? How can I use something similar to the first code sample while maintaining the animations?
I guess this is another SwiftUI bug. At first glance, I thought it was about Identifiable
. However, after modifying the object model, it makes no difference. You can fix it by nest list element within any component, such as:
HStack {
SubView(val: ob)
.onTapGesture {
objects.removeAll { $0 == ob }
}
}