SwiftUI 列表更新缓慢

4

我有一个包含数千项的 SwiftUI 列表。每个项如下:

class Item: Codable, Identifiable {
    var id = UUID()
    var prop1 = ""
    var prop2 = ""
}

现在我这样做:

List(store.items.indices, id: \.self) { index in
    DetailView(item: self.$store.items[index])
}.id(UUID())

我在循环中使用索引,因为我必须传递一个绑定到DetailView中。现在DetailView附加到Item的属性的文本字段。当DetailView更改Item的属性时,它会导致列表刷新所有项目,这是不希望的。此外,当其中一个属性更改时,仍然重要的是更新主视图,因为在macOS上,即使单击其中一个项,主视图仍然可见。我的问题是如何使从列表传入的Item更改时只更新该行?我还尝试了一种解决方案,其中我使用LazyVStack,它解决了性能问题,但我将List放在NavigationView中,而LazyVStack似乎不支持它。非常感谢任何建议。

你能展示一个完整的独立演示吗?并指出你发现问题的环境版本? - Asperi
如果您没有使用List提供的特定功能,那么使用ScrollView与LazyVStack可以帮助消除一些List的开销。在SwiftUI中,列表(Lists)的性能表现还不完全理想。 - Pranav Kasetti
我还会建议您审查在self.$store中使用的Published、State和Binding修饰符,因为这些属性的每次更改都会导致整个UI更新。尽可能限制这些修饰符的使用,同时保持功能性。 - Pranav Kasetti
2个回答

2
从列表中删除.id(UUID())
默认情况下,列表差异会更改,仅更新受影响的行。对于非常大的数据集,使用.id(UUID())技巧可以强制整个列表在发生变化时重新加载,这可能比尝试将大型数据集进行差异更快。看起来你不需要它,因此没有必要包含它会更糟糕。
编辑:我认为按索引绑定到数组不是问题,但很不寻常,最终可能会困扰你。

我建议使用Instruments来找出具体是什么在减慢它的速度:https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-instruments-to-profile-your-swiftui-code-and-identify-slow-layouts - Adam
我知道是什么导致了它的减速,那就是每次我在“Item”类中更改属性时,它都会更新整个列表。 - NewAppleUser1234

0

如果您不需要 List 特定的功能,那么在 ScrollView 中可以使用 LazyVStack。目前 List 不如 LazyVStack 高效(这是苹果的一个 bug)。

ScrollView {
    LazyVStack {
        ForEach(store.items.indices) { index in
            DetailView(item: self.$store.items[index])
        }
    }
}

这解决了性能问题,但是我正在NavigationView中使用DetailView,所以它并不真正起作用。 - NewAppleUser1234
我不明白为什么这样做不行,如果你将滚动视图嵌入导航视图中?无论如何,那是一个单独的问题,与此问题无关。 - Pranav Kasetti
1
已确认适用于iOS 15和Xcode 13.2.1。从List切换到ScrollView + LazyVStack立即解决了性能问题,并且NavigationLink仍然可以用于详细视图。 - Collierton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接