Performance Issue with Swiftui List

Bad performance of large SwiftUI lists on macOS

If you want to stay with List because you need all this nice features like selection, reordering, easy drag & drop... you will have to help SwiftUI estimate the total height of your list by having a fixed size for your rows. (I think this is the same in UIKit where performance will significantly improve if you are able to estimate the row height for each entry.)

So in your example, modify your row code as follows:

HStack {
Text("\(word.rank)")
Text(word.word)
}
.frame(width: 500, height: 15, alignment: .leading)
.tag(word)

I know it is an ugly solution because it doesn't dynamically adjust to the font size but it reduces the rendering time on my M1 Max based Mac from 2s down to 0.3s for a list of 10,000 words.

Performance issue when creating a list of 1000 elements in SwiftUI

There are a couple of issues with the code provided. The most important is you are not using a List just a ForEach nested in a ScrollView, which is like equivalent of placing 1000 UIViews in a UIStack - not very efficient. There is also a lot of hardcoded dimensions and quite a few of them are duplicates but nevertheless add a significant burden when the views are calculated.

I have simplified quite a lot and it runs with n = 10000 without crashing:

struct ContentView: View {

var body: some View {
GeometryReader { geometry in
NavigationView {
ScrollView(.horizontal) {
HStack {
ForEach(0..<3) { _ in
ListView(n: 10000)
.frame(width: geometry.size.width - 60)
}
} .padding([.leading], 10)
}
}
}
}
}

struct ListView: View {

var n: Int

@State var posts = [Post(id: UUID(), title: "1", description: "11"),
Post(id: UUID(), title: "2", description: "22"),
Post(id: UUID(), title: "3", description: "33")]

var body: some View {
List(0..<self.n) { n in
RowView(post: self.posts[0])
.frame(height: 200)
}
}
}

struct RowView: View {

var post: Post

var body: some View {
HStack {
Spacer()
VStack {
Spacer()
Text(self.post.title)
Text(self.post.description)
Spacer()
}
Spacer()
} .background(RoundedRectangle(cornerRadius: 10)
.fill(Color(#colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1))))
}
}


Related Topics



Leave a reply



Submit