Проблемы с производительностью со списком SwiftUI - PullRequest
0 голосов
/ 06 января 2020

У меня есть список с отображением результата динамического c FetchRequest.

Код работает нормально, но с большим набором результатов (например, 3000), список строится довольно медленно, когда динамический c предикат изменен.

struct ItemList: View {
    @State var startsWith: String = "A"

    var body: some View {
        NavigationView {
            VStack {
                TextField("Startswith", text:$startsWith)
                FilterRequestList(filter: startsWith)
            }
            .navigationBarTitle("Tasks CD")
        } 
    }
} 


struct FilterRequestList: View {
    var fetchRequest: FetchRequest<Item>

    init(filter: String) {
        if filter == "" {
            fetchRequest = FetchRequest<Item>(entity: Item.entity(),
                                              sortDescriptors: [],
                                              predicate: nil)
        } else {
            fetchRequest = FetchRequest<Item>(entity: Item.entity(),
                                              sortDescriptors: [],
                                              predicate: NSPredicate(format: "title BEGINSWITH %@", filter))
        }
    }

    var body: some View {
        VStack {
            Text("Count: \(fetchRequest.wrappedValue.count)")
            List(fetchRequest.wrappedValue, id: \.self) { item in
                Text("\(item.title) ")
            }
        }
    }
}

Есть идеи, как это улучшить?

Обновление: Что я обнаружил: Первый Список довольно быстрый, но если Запускается с изменением состояния, перезагрузка происходит очень медленно. Я добавил

FilterRequestList(filter: startsWith)
    .onAppear(perform: { print("appear F") })
    .onDisappear(perform: { print("disappear F") })

и обнаружил, что FilterRequestList не исчезает и не появляется снова при смене фильтра.

Может ли это быть проблемой? Как можно навязать отдых?

1 Ответ

0 голосов
/ 11 января 2020

Благодаря Полу Хадсону я нашел решение проблемы. В «https://www.youtube.com/watch?v=h0SgafWwoh8» он объясняет это подробно.

Вы просто должны добавить модификатор

.id(UUID())

в список.

Проблема заключалась в том, что swiftUI пытается обнаружить любые изменения из старого списка в новый, чтобы оживить изменения. С модификатором старый и новый список для swiftUI не являются одинаковыми списками (из-за постоянно меняющегося идентификатора), поэтому нет необходимости обнаруживать изменения. Swift может просто создать новый список очень быстро. Единственный недостаток в том, что, следовательно, нет анимации.

struct ItemList: View {
    @State var startsWith: String = "A"

    var body: some View {
        NavigationView {
            VStack {
                TextField("Startswith", text:$startsWith)
                FilterRequestList(filter: startsWith)
            }
            .navigationBarTitle("Tasks CD")
        } 
    }
} 


struct FilterRequestList: View {
    var fetchRequest: FetchRequest<Item>

    init(filter: String) {
        if filter == "" {
            fetchRequest = FetchRequest<Item>(entity: Item.entity(),
                                              sortDescriptors: [],
                                              predicate: nil)
        } else {
            fetchRequest = FetchRequest<Item>(entity: Item.entity(),
                                              sortDescriptors: [],
                                              predicate: NSPredicate(format: "title BEGINSWITH %@", filter))
        }
    }

    var body: some View {
        VStack {
            Text("Count: \(fetchRequest.wrappedValue.count)")
            List(fetchRequest.wrappedValue, id: \.self) { item in
                Text("\(item.title) ")
            }
            .id(UUID())
        }
    }
}
...