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.
CodePudding user response:
.task
is when the underlying UIView
appears, which in the case of List
is a UICollectionViewCell
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.
CodePudding user response:
I was found this solution on this way. May be help for you.
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 {
let arrData = dataSource.keys.sorted()
List {
ForEach(Array(arrData), 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)")
}
}
}
}
}