SwiftUI @Binding 值无法更改并调用了 init
SwiftUI @Binding value can not change and called 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 = [=10=] }
}
}
struct ContentView: View {
@State var value = 0
var body: some View {
VStack {
Text("(parent) \(self.value)")
ChildView(value: $value)
}
}
}
但是当我在ContentView里去掉Text("(parent) \(self.value)")
的时候,好像就正常了
发生这种情况是因为任何时候 ChildView
都被 init
初始化了 - 这发生在 ContentView
的 body 被重新计算时 - 它创建了 [=15 的新实例=] 的值为 0
.
首先确定谁“拥有”数据。如果它是一些外部 object,比如 ViewModel
,那么它应该在实例可能是 longer-lived 的地方实例化,例如在 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
我想做一个选择器使用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 = [=10=] }
}
}
struct ContentView: View {
@State var value = 0
var body: some View {
VStack {
Text("(parent) \(self.value)")
ChildView(value: $value)
}
}
}
但是当我在ContentView里去掉Text("(parent) \(self.value)")
的时候,好像就正常了
发生这种情况是因为任何时候 ChildView
都被 init
初始化了 - 这发生在 ContentView
的 body 被重新计算时 - 它创建了 [=15 的新实例=] 的值为 0
.
首先确定谁“拥有”数据。如果它是一些外部 object,比如 ViewModel
,那么它应该在实例可能是 longer-lived 的地方实例化,例如在 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