首页 > 解决方案 > SwiftUI 列表的性能问题

问题描述

我有一个显示动态 FetchRequest 的结果的列表。

代码工作正常,但结果集更大(例如 3000),当动态谓词更改时,列表的构建速度很慢。

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) ")
            }
        }
    }
}

任何想法,如何改进?

更新: 我发现:第一个 List 相当快,但如果 startsWith 状态发生变化,重新加载非常慢。我添加了

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

并发现,FilterRequestList当过滤器改变时,它并没有消失和重新出现。

这可能是问题吗?怎么可以强迫消遣?

标签: swiftswiftuiswiftui-list

解决方案


感谢 Paul Hudson,我找到了问题的解决方案。在“ https://www.youtube.com/watch?v=h0SgafWwoh8 ”中,他详细解释了这一点。

您只需添加修饰符

.id(UUID())

到列表中。

问题是,swiftUI 会尝试检测从旧列表到新列表的任何更改,以便为更改设置动画。使用修饰符,swiftUI 的旧列表和新列表不是同一个列表(因为 id 总是在变化),因此无需检测更改。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())
        }
    }
}

推荐阅读