SwiftUI@Binding值不能更改并调用init



我想让一个选择器使用SwiftUI,当我在ChildView中更改值时,它不会更改,并调用ChildView init。

class ViewModel: ObservableObject {
@Published var value: Int

init(v: Int) {
self.value = v
}
}
struct ChildView: View {
@Binding var value: Int
@ObservedObject var vm = ViewModel(v: 0)

init(value: Binding<Int>) {
self._value = value
print("ChildView init")
}

var body: some View {
VStack {
Text("param value: (value)")
Text("@ObservedObject bar: (vm.value)")
Button("(child) bar.value++") {
self.vm.value += 1
}
}
.onReceive(vm.$value) { value = $0 }
}
}
struct ContentView: View {
@State var value = 0

var body: some View {
VStack {
Text("(parent) (self.value)")
ChildView(value: $value)
}
}
}

但当我在ContentView中删除Text("(parent) (self.value)")时,这似乎是正常的。

之所以会发生这种情况,是因为每当ChildViewinit实例化时(当ContentView的主体被重新计算时(,它都会创建一个值为0ViewModel的新实例。

首先确定谁";拥有";数据。如果它是某个外部对象,如ViewModel,那么它应该在某个实例寿命更长的地方进行实例化,例如在ContentView中(但这将取决于您的真实用例(:

struct ContentView: View {
@State var value = 0
var childVm = ViewModel(v: 0)

var body: some View {
VStack {
Text("(parent) (self.value)")
ChildView(vm: childVm, value: $value)
}
}
}
struct ChildView: View {
@Binding var value: Int
@ObservedObject var vm: ViewModel

init(vm: ViewModel, value: Binding<Int>) {
self._value = value
self.vm = vm
print("ChildView init")
}
// ...
}

通常,所描述的行为是意料之中的,因为value的真相来源在父级中,通过绑定更新它可以更新所有使用它的地方。这将导致重建父实体,因此重新创建子视图。

SwiftUI 2.0

解决方案是简单使用状态对象

struct ChildView: View {
@Binding var value: Int
@StateObject var vm = ViewModel(v: 0)   // << here !!
// ... other code

SwiftUI 1.0+

使用更新的绑定值初始化视图模型

struct ChildView: View {
@Binding var value: Int
@ObservedObject var vm: ViewModel    // << declare !!
init(value: Binding<Int>) {
self._value = value
self.vm = ViewModel(v: value.wrappedValue) // << initialize !!
// .. other code

最新更新