@State和@ObservedObject有什么区别,它们都可以用来保持状态吗?

时间:2019-12-31 02:07:21

标签: swiftui observedobject

当我用Google搜索“ State vs ObservedObject”时,第一个result来自Swift黑客组织,它说的是@ObservedObject

  

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

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

1 个答案:

答案 0 :(得分:2)

@ObservedObject不保持状态

  

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

单靠自己,你做不到。苹果documentation的话是关于@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由于属性更改而重新呈现视图时,将重置@ObservedObject

screenshot

相反,如果在@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属性更改,该值也不会重置:

screen shot