SwiftUI状态管理机制@Observable和@Environment
SwiftUI状态管理机制@Observable和@Environment

SwiftUI状态管理机制@Observable和@Environment

使用 @Observable 和 @Environment 是 SwiftUI 最新的状态管理机制,它引入了更简洁、类型安全的方式来共享和观察数据。

什么是 @Observable?

@Observable 是 Swift 宏,用于将类声明为可观察对象。它会自动生成必要的代码,使该类可以被 SwiftUI 自动观察,从而触发视图更新。

示例

@Observable
class Person {
    var name = "Fangjunyu"
    var age = 27
}

@Observable 会自动生成代码,使 Person 类的属性成为可观察的。

当 Person 的属性值发生变化时,绑定到这些属性的视图会自动刷新。

使用 @Environment 共享数据

@Environment 是 SwiftUI 提供的机制,用于在视图层次结构中共享数据对象,避免逐层传递。结合 @Observable,可以轻松实现这种共享。

完整示例

定义可观察对象
@Observable
class Person {
    var name = "Fangjunyu"
    var age = 27
}
将对象放入环境中

使用 .environment(person) 将 Person 对象注入视图的环境中:

struct ContentView: View {
    @State private var person = Person() // 创建可观察对象

    var body: some View {
        VStack {
            PeopleList()
        }
        .environment(person) // 将对象放入环境
    }
}
在子视图中读取环境对象

使用 @Environment(Person.self) 从环境中读取对象:

struct PeopleList: View {
    @Environment(Person.self) var person // 从环境中读取 Person

    var body: some View {
        VStack {
            Text("Person: \(person.name)")
            Text("Age: \(person.age)")
        }
    }
}

现在,PeopleList 自动从环境中获取 Person 对象,并响应其属性的变化。

数据绑定:与 @Bindable 一起使用

@Environment 中读取数据并不支持直接双向绑定。因为@Environment 只允许只读访问,不能直接通过它进行写操作。

因此,应该考虑使用@EnvironmentObject。

和传统 @EnvironmentObject 的对比

运行时注意事项

环境中必须存在对象

如果一个视图声明了 @Environment(Person.self),但在父视图中未通过 .environment(person) 注入该类型对象,应用会崩溃。

解决方法:确保在父视图中正确使用 .environment(person)。

注意:这个问题也会发生在预览中,因此需要在子视图的预览中使用:

#Preview {
    ResortView(resort: Resort.example)
        .environment(Favorites())
}

让SwiftUI预览继续工作。

双向绑定问题

目前(iOS 17),@Environment 的对象属性不能直接绑定。

总结

@Observable 和 @Environment 提供了一种现代、类型安全且简洁的状态管理方式。

适用场景

需要局部共享的轻量级数据。

希望避免使用传统的 ObservableObject 和 Combine。

局限性

当前不支持直接绑定,可能在未来的 iOS 版本中改进。

这种机制可以使代码更简洁,更符合 SwiftUI 的声明式编程风格,尤其适合构建复杂的应用数据共享场景。

相关文章

1、Swift @Observable属性包装器:https://fangjunyu.com/2024/11/03/swift-observable%e5%b1%9e%e6%80%a7%e5%8c%85%e8%a3%85%e5%99%a8/

2、Sharing @Observable objects through SwiftUI’s environment:https://www.hackingwithswift.com/books/ios-swiftui/sharing-observable-objects-through-swiftuis-environment

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注