Consider the following code example (you can download it here):
struct Item: Identifiable {
var id = UUID()
var name: String
}
struct Row: View {
var item: Item
static var counter = 0
init(item: Item) {
self.item = item
Row.counter += 1
print(Row.counter)
}
var body: some View {
Text(item.name)
}
}
struct ContentView: View {
@State var items = (1...1000).map { Item(name: "Item ($0)") }
var body: some View {
List {
ForEach(items) {
Row(item: $0)
.swipeActions(edge: .leading) {
Button("Action", action: {})
}
}
}
}
}
Running this code prints out the numbers 1
to 21
, so around the amount of rows that are visible on the screen.
Now if I wrap the ForEach
statement in a Section
, the numbers 1
to 1000
are printed out. Hence, there is no cell reuse and all rows are loaded at once.
Section {
ForEach(items) {
Row(item: $0)
.swipeActions(edge: .leading) {
Button("Action", action: {})
}
}
}
If I remove the swipe action, the numbers 1
to 18
are printed out.
Section {
ForEach(items) {
Row(item: $0)
}
}
Is this a known issue or what am I doing wrong here?
3
Answers
I also encountered this issue even without the swipe action. I create a new SectionView for Lists with
.insetGroup
style until Apple fixes it. The downside is that the section header and footer are not equal to the original view.It was tested and is working with iOS 15 and 16.
Using it with your given code example Item must conform to Equatable.
Concept:
onAppear { }
.Code:
Output
As a workaround, you can createa
LazyVStack
with aForEach
loop and style it as a List. Of course in this case you’ll need to implement your own logic for deleting items. You can refer to this project where I replicated the Apple’s List using a LazyVStackhttps://github.com/MrRonanX/Test-Task.-List-Swipe-Actions