Home > database >  Bad performance of large SwiftUI lists on macOS
Bad performance of large SwiftUI lists on macOS

Time:05-02

I have a SwiftUI app which displays large lists of 1000 to 5000 items. I noticed that on macOS displaying such a long list has very bad performance. It takes several seconds for SwiftUI to render the list. This is independent of the complexity of the row views. Even if the rows are only Text() views.

On iOS, however, the same list would render almost instantaneously.

My code for the list view looks like this:

struct WordList: View {
    
    @EnvironmentObject var store: Store
    @State var selectedWord: RankedWord? = nil

    var body: some View {
        List(selection: $selectedWord) {
            ForEach(store.words) { word in
                HStack {
                    Text("\(word.rank)")
                    Text(word.word)
                }
                .tag(word)
            }
        }
    }
}

Does anybody know some tricks to speed this up? Or is this a general problem on macOS 12 and we need to hope Apple improves this in the next major OS update?

I have also created a very simple sample app to test and demonstrate the list performance and of which the code above is taken from. You can browse / download it on GitHub

CodePudding user response:

List seems to be not lazy on macOS. But you can use TableView wich is, and supports single or multiple selection:

struct WordList_mac: View {
    
    @EnvironmentObject var store: Store
    @State var selectedWord: RankedWord.ID? = nil

    var body: some View {

        Table(store.words, selection: $selectedWord) {
            TableColumn("Rank") { Text("\($0.rank)") }
            TableColumn("Word", value: \.word)

        }
    }
}

CodePudding user response:

What you wrote is fully generic code with say 5,000 user interface elements. A good old UITableView will handle this easily - it is one UI element instead of 5,000, and it creates reusable cells just for rows of the table that are visible on the screen (say 30 on an iPad, instead of 5,000.

  • Related