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 last task 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
Text("(row)")
}
.task {
print("TASK (section)")
}
} header: {
Text("Section (section)")
}
}
}
}
}
Does anyone has an explanation ? Am I missing something ?
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.
2
Answers
.task
is when the underlyingUIView
appears, which in the case ofList
is aUICollectionViewCell
and those only appear once and are reused when scrolling so have already appeared so.task
won’t run again.Btw
ForEach
is not a for loop.I was found this solution on this way. May be help for you.