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

SwiftUI 5中使用@Observable对象时是否无需@State属性包装器?

@Observable 场景下 @State 的作用疑问

我在苹果开发者文档的「在视图中更改模型数据」章节看到:

借助SwiftUI的Observation,视图无需使用属性包装器或绑定即可支持数据变更

于是编写了如下测试代码:

struct ContentView: View {
    var person: Person = .init(id: UUID(), name: "Stacey")
    
    var body: some View {
        VStack {
            Button {
                person.name = "Sarah"
            } label: {
                Text("change name")
            }
            
            AnotherView()
                .environment(person)
            
            Text("Name: \(person.name)")
        }
    }
}

@Observable
class Person: Identifiable {
    var id: UUID
    var name: String
    
    init(id: UUID, name: String) {
        self.id = id
        self.name = name
    }
}

代码能正常编译运行,但我有疑问:既然用@Observable对象时无需@State也能读写变量,那@State还有什么意义?


解答

1. 避免视图重建导致的数据丢失

@Observable是作用在引用类型上的观察机制,但直接用var person声明的对象,是存储在视图结构体内部的。当SwiftUI因为父视图刷新、布局变化等原因重建ContentView结构体时,会重新初始化一个新的Person实例,之前修改的name数据会直接丢失。

而@State会把对象存储在SwiftUI专门的视图状态容器中,和视图结构体的生命周期解耦,无论视图重建多少次,都能保留原来的Person实例和数据。

2. 触发视图UI更新

你的示例中点击按钮修改person.name后,界面上的Text("Name: \(person.name)")并不会更新——因为var person是视图结构体的普通属性,SwiftUI不会监听它引用的@Observable对象的变化。虽然你能修改对象的属性,但视图本身不会触发body的重新计算。

如果把var person改成@State private var person = Person(...),SwiftUI会自动跟踪这个@Observable对象的变化,当对象的属性更新时,会立刻触发视图刷新,UI才会同步显示最新的name值。

3. 明确视图的私有状态边界

@State的核心作用是标记视图的私有内部状态,适合存储仅当前视图需要管理的数据。而@Observable对象更多用于跨视图共享的模型数据(比如通过environment传递给子视图)。如果某个@Observable对象是当前视图独有的,用@State持有它,既能保证数据持久,又能让视图响应其变化,这是普通属性做不到的。


内容的提问来源于stack exchange,提问作者JAHelia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:53:18