为何SwiftUI Table无法追踪@Observable对象的数据变更?
SwiftUI Table无法追踪Observation框架下的Item属性变更,List正常工作
我尝试使用Observation框架构建SwiftUI Table,但Table无法追踪数据的变更,不过List却能正常追踪。相关代码如下:
@Observable final class Item: Identifiable { var id: UUID var value: Int init(value: Int) { self.id = UUID() self.value = value } } @Observable final class AppModel { var items: [Item] init() { var items: [Item] = [] for i in 0...10 { items.append(Item(value: i)) } self.items = items } func updateValue() { let index = Int.random(in: 0..<items.count) items[index].value = Int.random(in: 200...300) } func startTimer() { let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.updateValue() } } } @main struct TestApp: App { @State private var appModel = AppModel() var body: some Scene { WindowGroup { ContentView() .environment(appModel) } } } struct ContentView: View { @Environment(AppModel.self) private var appModel var body: some View { VStack { Table(appModel.items) { TableColumn("Value") { Text("\($0.value)") } } List(appModel.items) { Text("\($0.value)") } } .padding() .frame(minHeight: 640) .onAppear { appModel.startTimer() } } }
问题原因
Table与List的数据源监听逻辑存在差异:
- List会自动为每个
Identifiable元素建立细粒度的监听,能够感知到数组内部单个Item对象的属性变更。 - 而Table默认仅监听数组本身的结构变化(比如元素增删),不会自动追踪数组内Item的属性更新,除非显式告知SwiftUI需要监听这些属性。
解决方案
你可以通过以下两种方式修复这个问题:
方法一:使用@Bindable包裹Item
在TableColumn的内容闭包中,用@Bindable修饰Item参数,让SwiftUI自动追踪其Observable属性的变化:
Table(appModel.items) { TableColumn("Value") { @Bindable var item in Text("\(item.value)") } }
方法二:显式添加observationTracking
通过observationTracking闭包明确声明需要监听的属性,触发视图更新:
Table(appModel.items) { TableColumn("Value") { item in Text("\(item.value)") .observationTracking { _ = item.value // 声明对item.value的依赖 } } }
两种方法都能让Table感知到Item的value属性变化并实时更新视图,其中方法一的代码更简洁直观,是推荐的做法。
内容的提问来源于stack exchange,提问作者Nikolai Nagornyi
相关产品推荐
相关产品推荐

