0

I have a List in SwiftUI App on MacOS with e.g. 10.000 entries.
Trying like the example below is horribly slow.

Adding .id(UUID()) to the List, which was advised in a prior post, makes it a bit quicker but still not fluid.
Even worst, adding .id(UUID()) to the list, the list then cannot be navigates by the arrow-key (up/down).

Is there a better way to achieve this?

struct TestViews_MacOS_BigList: View {
  @State var selectedItem: String?
  var items: [String]

  var body: some View {
    List(items,id: \.self, selection: $selectedItem ) { item in
      Text("\(item)").tag("\(item)")
    }
    //.id(UUID())
  }
}

func testnames()->[String]{
  var list: [String] = []
  for i in 1...10000 {
    list.append("Sting Nr \(i)")
  }
  return list
}
mica
  • 3,358
  • 3
  • 29
  • 54

2 Answers2

0

Those are too many Views to have sitting around. You need to use CoreData or some other manual way to Batch load items and a way to only have a certain number of Views/items fetched/loaded at a time.

An NSFetchedResultsController that specifies a batch size can help with that

let fetchRequest: NSFetchRequest<Item> = NSFetchRequest<Item>(entityName: "Item")
    fetchRequest.includesPendingChanges = false
    fetchRequest.fetchBatchSize = 20

When the fetch is executed, the entire request is evaluated and the identities of all matching objects recorded, but only data for objects up to the batchSize will be fetched from the persistent store at a time.

@FetchRequest might do it as well, it was made for SwiftUI so it should compensate but the documentation does not specify.

lorem ipsum
  • 10,403
  • 2
  • 10
  • 31
  • In the real code, I use an @FetchRequest. It's unfortunately the same behavior. – mica Jan 31 '21 at 19:26
  • 1
    Try the [FetchedResultsController wrapped in an ObservableObject](https://m.youtube.com/watch?v=-U-4Zon6dbE) then. That doesn’t work try a [UITableView as the original way](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html) to use this controller. – lorem ipsum Jan 31 '21 at 19:36
-2

Try using LazyVStack since it uses memory efficiently as below:

struct TestViews_MacOS_BigList: View {
 @State var selectedItem: String?
 var items: [String]
 var body: some View {
  ScrollView {
   LazyVStack{
    ForEach(items, id: \.self, content: { item in
     HStack{
      Button(action: {
       selectedItem = item
      }, label: {
       Text("Select ")
      })
      Text("\(item)").tag("\(item)")
    }
  })
 }
}

}

}

JohnD
  • 1