You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:25:03