SwiftUI Example

如何使用 @EnvironmentObject 在视图之间共享数据?

对于应与应用程序中的许多视图共享的数据,SwiftUI 为我们提供了 @EnvironmentObject 属性包装器。 这样一来,我们就可以在需要的任何地方共享模型数据,同时还可以确保在数据更改时我们的视图自动保持更新。

@EnvironmentObject 视为在许多视图上使用 @ObservedObject 的更智能,更简单的方法。 与其在视图 A 中创建一些数据,然后将其传递到视图 B,视图 C,然后在最终使用它之前将其传递给视图 D,您可以在视图中创建它并将其放入环境中,以便视图BCD将 自动访问它。

就像 @ObservedObject 一样,您永远不会将值分配给 @EnvironmentObject 属性。 相反,它应该从其他地方传入,最终您可能会想使用 @StateObject 在某个地方创建它。

但是,与 @ObservedObject 不同,我们不会手动将对象传递到其他视图中。 取而代之的是,我们将数据发送到一个名为 environmentObject() 的修饰符中,该修饰符使该对象及其视图中的其他视图在 SwiftUI 的环境中可用。

注意:环境对象必须由祖先视图提供-如果 SwiftUI 找不到正确类型的环境对象,则会崩溃。 这也适用于预览,因此请小心。

为了演示环境对象,我们将定义三件事:

这是代码:

// 我们的可观察对象类
class GameSettings: ObservableObject {
    @Published var score = 0
}

// 期望找到 GameSettings 对象的视图
// 在环境中,并显示其得分。
struct ScoreView: View {
    @EnvironmentObject var settings: GameSettings
    var body: some View {
        Text("Score: \(settings.score)")
    }
}

struct ContentView: View {
    @StateObject var settings = GameSettings()
    var body: some View {
        NavigationView {
            VStack {
                // 写入 environment settings 的按钮
                Button("Increase Score") {
                    settings.score += 1
                }
                NavigationLink(destination: ScoreView()) {
                    Text("Show Detail View")
                }
            }
            .frame(height: 200)
        }
        .environmentObject(settings)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我想在该代码中挑选出几个重要的部分:

警告:既然我们的视图依赖于当前的环境对象,那么还必须更新预览代码以提供一些示例设置供您使用,这一点很重要。 例如,为预览使用诸如 ScoreView().environmentObject(GameSettings()) 之类的东西就可以做到。

如果需要向环境中添加多个对象,则应添加多个 environmentObject() 修饰符–只需一个接一个地调用它们即可。