4

当我用 Google 搜索“State vs ObservedObject”时,第一个结果来自 Hacking with Swift,它说@ObservedObject

这与@State 非常相似,只是现在我们使用的是外部引用类型,而不是像字符串或整数这样的简单本地属性。

我可以@ObservedObject用来创建持久状态吗?它是否像@State简单属性和@ObservedObject复杂对象一样简单,还是有更多细微差别?

4

1 回答 1

7

@ObservedObject不持久状态

我可以@ObservedObject用来创建持久状态吗?

就其本身而言,你不能。Apple文档有这样的说法@State

给定类型的持久值,视图通过它读取和监视该值。

但我发现没有提到持久性,@ObservedObject所以我构建了这个小演示,确认@ObservedObject不持久状态:

class Bar: ObservableObject {
  @Published var value: Int

  init(bar: Int) {
    self.value = bar
  }
}

struct ChildView: View {
  let value: Int
  @ObservedObject var bar: Bar = Bar(bar: 0)

  var body: some View {
    VStack(alignment: .trailing) {
      Text("param value: \(value)")
      Text("@ObservedObject bar: \(bar.value)")
      Button("(child) bar.value++") {
        self.bar.value += 1
      }
    }
  }
}

struct ContentView: View {
  @State var value = 0

  var body: some View {
    VStack {
      Spacer()
      Button("(parent) value++") {
        self.value += 1
      }
      ChildView(value: value)
      Spacer()
    }
  }
}

每当您单击value++按钮时,都会导致重新渲染,ChildView因为value属性已更改。当视图由于属性更改而重新渲染时,它的@ObservedObjects 将被重置

截屏

相反,如果您向 中添加一个@State变量,ChildView您会注意到在重置时它的值不会@ObservedObject重置。

使用持久状态@ObservedObject

要使用 保持状态,请在父视图中@ObservedObject实例化混凝土。因此,要修复前面的示例,将如下所示:ObservableObject@State

struct ChildView: View {
  let value: Int
  @ObservedObject var bar: Bar  // <-- passed in by parent view

  var body: some View {
    VStack(alignment: .trailing) {
      Text("param value: \(value)")
      Text("@ObservedObject bar: \(bar.value)")
      Button("(child) bar.value++") {
        self.bar.value += 1
      }
    }
  }
}

struct ContentView: View {
  @State var value = 0
  @State var bar = Bar(bar: 0)  // <-- The ObservableObject

  var body: some View {
    VStack {
      Spacer()
      Button("(parent) value++") {
        self.value += 1
      }
      ChildView(value: value, bar: bar).id(1)
      Spacer()
    }
  }
}

类的定义与Bar第一个代码示例相同。现在我们看到,即使value属性发生变化,该值也不会重置:

截屏

于 2019-12-31T02:07:21.250 回答