I'm encountering a strange behaviour with List when using section and either task or onAppear.
Let's say I have a list with sections and rows in each section. When I put a task to run a async task when each row appears, it doesn't call it even though it's displayed on screen. The same problem applies when using onAppear instead of task.
It's easily reproducible with the given example. You can just run and scroll down to the bottom. You'll notice that the onAppear
for the last row isn't called despite the row and the section is on screen.
struct ContentView: View {
private var dataSource: [Int: [String]] = (0..<30).reduce([Int: [String]]()) { result, key in
var result = result
let items = (0..<4).map { "Item \($0)" }
result[key] = items
return result
}
var body: some View {
List {
ForEach(Array(dataSource.keys), id: \.self) { section in
let rows = dataSource[section]
Section {
ForEach(rows ?? [], id: \.self) { row in
let text = "\(section)-\(row)"
Text(text)
.onAppear {
print("ROW ON APPEAR \(text)")
}
}
.onAppear {
print("ON APPEAR \(section)")
}
} header: {
Text("Section \(section)")
}
}
}
}
}
Does anyone have an explanation ? Am I missing something ? As is my understanding of the documentation, onAppear should be called every time the view appears on screen.
The interesting thing is that is seems to work fine when they're no sections.... Could it just be a bug in SwiftUI?
I managed to fix this problem by using a ScrollView which embeds a LazyVStack, but by doing so I'm loosing some of the features from List, such as swipe to delete.