I have discovered that the onAppear
method of views inside of a SwiftUI list is called inconsistently, based on the presence of a listStyle
. The onAppear
method is called 100% of the time when there is no listStyle
applied, but it is called irregularly when there is a listStyle applied.
Here is demo code:
struct TextRow: View {
@State private var didAppear: Bool = false
private let title: String
init(title: String) {
self.title = title
}
var rowTitle: String {
if didAppear {
return title + " (didAppear)"
} else {
return title
}
}
var body: some View {
Text(rowTitle)
.onAppear {
didAppear = true
}
}
}
struct Section: Hashable {
let title: String
let rows: [String]
}
struct ContentView: View {
var content: [Section] {
var rows = [String]()
for i in 0..<20 {
rows.append("Row \(i)")
}
let section1 = Section(title: "Section 1", rows: rows)
var rows2 = [String]()
for i in 0..<20 {
rows2.append("Row \(i)")
}
let section2 = Section(title: "Section 2", rows: rows2)
return [section1, section2]
}
var body: some View {
List {
ForEach(content, id: \.self) { section in
Text(section.title)
ForEach(section.rows, id: \.self) { row in
TextRow(title: row)
}
}
}
// .listStyle(.grouped) // <-- this will trigger different behavior
.navigationBarTitle("Countries")
.padding()
}
}
Is this expected?
Here is the bad behavior:
Here is the proper behavior (no list style):