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

Posted Forever_wj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SwiftUI之如何使用@EnvironmentObject在视图之间共享数据相关的知识,希望对你有一定的参考价值。

  • 对于应该与应用程序中的许多视图共享的数据,SwiftUI 为我们提供了 @EnvironmentObject 属性包装器,这让我们可以在任何需要的地方共享模型数据,同时还确保我们的视图在数据更改时自动保持更新。
  • 可以把 @EnvironmentObject 看作在许多视图上使用,是一种比 @ObservedObject 更智能、更简单的方式。与其在视图 A 中创建一些数据,然后将其传递给视图 B,然后是视图 C,然后是视图 D 才最终使用它,可以在视图 A 中创建它并将其放入环境中,以便视图 B、C 和 D 将自动访问它。
  • 就像 @ObservedObject 一样,永远不会为 @EnvironmentObject 属性赋值。相反,它应该从其他地方传入,最终您可能想要使用 @StateObject 在某处创建它。但是,与 @ObservedObject 不同的是,我们不会手动将对象传递到其它视图中。相反,使用将数据发送到一个名为 environmentObject() 的修饰符,这使得该对象在 SwiftUI 的环境中可用于该视图以及其中的任何其它对象(需要注意:环境对象必须由父视图提供,如果 SwiftUI 找不到正确类型的环境对象,程序就会崩溃,这也适用于预览,所以要小心)、
  • 为了演示环境对象,我们将定义三件事:
    • 一个 GameSettings 类,其中包含一个名为 score 的已发布属性;
    • 期望在环境中接收 GameSettings 对象并显示其 score 属性的 ScoreView 视图;
    • 一个创建 GameSettings 对象的 ContentView 视图,有一个按钮可以将 1 添加到它的 score 属性,还有一个 NavigationLink 来显示详细信息视图。
  • 如下所示:
// Our observable object class
class GameSettings: ObservableObject 
    @Published var score = 0


// A view that expects to find a GameSettings object
// in the environment, and shows its score.
struct ScoreView: View 
    @EnvironmentObject var settings: GameSettings

    var body: some View 
        Text("Score: \\(settings.score)")
    


// A view that creates the GameSettings object,
// and places it into the environment for the
// navigation view.
struct ContentView: View 
    @StateObject var settings = GameSettings()

    var body: some View 
        NavigationView 
            VStack 
                // A button that writes to the environment settings
                Button("Increase Score") 
                    settings.score += 1
                

                NavigationLink(destination: ScoreView()) 
                    Text("Show Detail View")
                
            
            .frame(height: 200)
        
        .environmentObject(settings)
    

  • 分析该代码中几个重要部分:
    • 就像 @StateObject 和 @ObservedObject 一样,所有与 @EnvironmentObject 一起使用的类都必须符合ObservableObject 协议;
    • 将 GameSettings 放入导航视图的环境中,这意味着导航视图中的所有视图都可以根据需要读取该对象,以及导航视图显示的任何视图;
    • 当使用 @EnvironmentObject 属性包装器时,声明希望接收的事物类型,但并没有创建它,毕竟我们希望从环境中接收它;
    • 因为我们的细节视图显示在导航视图中,所以它可以访问相同的环境,这意味着它可以读取我们创建的 GameSettings 对象;
    • 不需要将环境中的 GameSettings 实例与 ScoreView 中的 settings 属性显式关联,SwiftUI 会自动确定它在环境中具有一个 GameSettings 实例,因此它就是它使用的实例。
  • 既然我们的视图依赖于存在的环境对象,那么更新预览代码以提供一些要使用的示例设置也很重要。 例如,使用 ScoreView().environmentObject(GameSettings()) 之类的东西进行预览应该这样做。
  • 如果需要向环境添加多个对象,应该添加多个 environmentObject() 修饰符,只需一个接一个地调用它们。

以上是关于SwiftUI之如何使用@EnvironmentObject在视图之间共享数据的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI之深入解析如何定制视图的动画和转场

SwiftUI之深入解析如何使用组合矩形GeometryReader创建条形(柱状)图

SwiftUI之深入解析如何使用组合矩形GeometryReader创建条形(柱状)图

SwiftUI之如何创建常量绑定与自定义绑定

Swift之深入解析SwiftUI属性包装器如何处理结构体

SwiftUI之NavigationView的基础使用与进阶实践