I'm observing a weird issue with SwiftUI
List
s on macOS (they do work as expected on iOS). The problem is that the List
calls the init
& body
of every row, even if those rows are not on screen (and might never be shown).
If I replace the List
with a ScrollView
+ LazyVStack
, it does work as expected (only those rows which are going to be rendered get their init
& body
called). Of course, this is is not an ideal workaround because you loose the built-in benefits of using a List
(mainly selection in my case).
I did expect that under the hood, SwiftUI
would use the same mechanism as NSTableView
(which loads cells on demand). Historically I'm an iOS dev, so I'm used to cellForRowAtIndexPath
coming from UITableView
.
Here's a quick gist demonstrating the issue:
import SwiftUI
@main
struct SwiftUIListVSLazyVStackApp: App {
let numbers = (0...100).map { $0 }
var body: some Scene {
WindowGroup {
/*
List calls the init & the body of *every* element on the list, even if it's not being displayed.
This is unexpected because a tableView usually only loads the visible cells as needed (cellForRowAtIndexPath)
*/
List(numbers) { number in
RowView(for: number, example: "list")
}
/*
A combination of ScrollView + LazyVStack achieves what's expected from the list. Only calls the init & body of
the element that's going to be displayed.
*/
// ScrollView {
// LazyVStack(alignment: .leading, spacing: 8) {
// ForEach(numbers) { number in
// RowView(for: number, example: "stack")
// }
// }
// }
}
}
}
struct RowView: View {
private let number: Int
private let example: String
init(for number: Int, example: String) {
print("Init \(example): \(number)")
self.number = number
self.example = example
}
var body: some View {
let _ = print("Body \(example): \(number)")
Text("\(number)")
.onAppear{ print("Appear \(example): \(number)") }
}
}
extension Int: Identifiable {
public var id: Int { self }
}
GitHub gist: https://gist.github.com/xmollv/7ecc97d8118c100e85698c5ff09a20dc
And a video to better show the issue if you can't run the code: https://gist.github.com/xmollv/7ecc97d8118c100e85698c5ff09a20dc?permalink_comment_id=4140623#gistcomment-4140623
Twitter thread: https://twitter.com/xmollv/status/1517158777882955779
Any help is very much appreciated!