Search code examples
swiftui-listswiftuiobservedobject

SwiftUI List freezes on @ObservedObject update


I have the List which automatically fetches more data near the end:

struct AdCardListView: View {
    @ObservedObject var model: AdListViewModel = AdListViewModel()

    var body: some View {
        List { ForEach(self.model.adArray.enumerated().map({ $0 }), id: \.element.id) { index, ad in
                AdCardView(ad: ad)
                    .onAppear {
                        DispatchQueue.main.async {
                            let count = self.model.adArray.count
                            if index >= count - 5 { //5 Views to the end, start loading more.
                                self.model.fetch(count: count)
                            }
                        }
                }
                }
            }
    }
}

Model looking like:

final class AdListViewModel: ObservableObject {
    @Published var adArray = [Ad]()
    ...
 func fetch(count: Int = 0) {
    ...
    DispatchQueue.main.async {
        self.adArray.append(contentsOf: newAds) //<-- problem here
    }
    ...
}

My problem: every @Published/@ObservedObject modification I have a little freeze when scroll list. Also, I found that List recalculates the body of all visible views + a few views above and below.

But I can't determine what leads to hangs of scrolling and fix it (maybe freeze is a transfer to a distance equal to (scrolling speed * rendering time)?

Why SwiftUI recalculate bodies on the existing views? They have not changed!

Can you help me?


Solution

  • Recreation of the body should not be an issue.I doubt that the performance issue is related with the update animations of the List.

    Did you try adding .id(UUID()) modifier to your List so that animations are discarded and the list is recreated after updates.