SwiftUI:使用@ObservedObject共享状态

如果您想使用一个类来保存SwiftUI数据——如果你想要做的是让该数在一个以上的视图之间共享——SwiftUI为我们提供了两个有用的属性包装器:@ObservedObject@EnvironmentObject。我们将晚一些研究@EnvironmentObject,现在让我们集中关注@ObservedObject

这是一些代码,用于创建User类,并在视图中显示该用户数据:

class User {
    var firstName = "Bilbo"
    var lastName = "Baggins"
}

struct ContentView: View {
    @State private var user = User()

    var body: some View {
        VStack {
            Text("Your name is \(user.firstName) \(user.lastName).")

            TextField("First name", text: $user.firstName)
            TextField("Last name", text: $user.lastName)
        }
    }
}

但是,该代码无法按预期工作:我们已将user属性标记为@State,该属性旨在跟踪本地结构体而非外部类。因此,我们可以在文本字段中输入内容,但是上面的文本视图不会更新。

为了解决这个问题,我们需要在类中的我们感兴趣的部分发生更改时告诉SwiftUI。所谓“感兴趣的部分”,是指应该使SwiftUI根据我们的类的属性变化重新加载视图的部分属性——您的类里面可能有很多属性,但是只有这种情况下,才应该暴露给外部。

我们的User类具有两个属性:firstNamelastName。每当这两个更改中的任何一个更改时,我们都希望通知正在关注我们类的所有视图我们的类发生了更改,以便可以重新加载它们。我们可以使用@Published属性观察器执行此操作,如下所示:

class User {
    @Published var firstName = "Bilbo"
    @Published var lastName = "Baggins"
}

@Published差不多是@State的一半:它告诉Swift,只要这两个属性中的任何一个发生更改,它都应该向任何正在关注它们的SwiftUI视图发送公告。

这些视图如何知道哪些类可以发出这些通知?那是另一个属性包装器@ObservedObject,它是@State的另一半——它告诉SwiftUI监视类中的任何的更改公告。

因此,将user属性更改为如下:

@ObservedObject var user = User()

我删除了那里的私有访问控制,但是是否使用它取决于您的使用情况——如果您打算与其他视图共享该对象,然后将其标记为private将引起混乱。

现在,我们正在使用@ObservedObject,我们的代码将不再编译。这不是问题,实际上是可以预期的并且很容易解决:@ObservedObject属性包装器只能用于符合ObservableObject协议的类型。该协议没有任何要求,实际上意味着“我们希望其他事物能够监视此更改”。

因此,将User类修改为:

class User: ObservableObject {
    @Published var firstName = "Bilbo"
    @Published var lastName = "Baggins"
}

现在我们的代码将再次编译,更好的是,它现在将能再次运行——您可以运行该应用程序,并在更改任一文本字段时查看文本视图更新。

如您所见,我们现在不仅仅只使用@State声明本地状态,还执行三个步骤:

  • 创建一个符合ObservableObject协议的类。
  • @Published标记一些属性,以便使用该类的所有视图在更改时都得到更新。
  • 使用@ObservedObject属性包装器创建我们的类的实例。

最终结果是我们可以将状态存储在一个外部对象中,甚至更好的是,我们现在可以在多个视图中使用该对象并将它们都指向相同的值。

译自 Sharing SwiftUI state with @ObservedObject

Previous: SwiftUI:为什么@State只适用于结构体 Hacking with iOS: SwiftUI Edition Next: SwiftUI:Sheet弹窗

赏我一个赞吧~~~

你可能感兴趣的:(SwiftUI:使用@ObservedObject共享状态)