当我有一个嵌套的 ObservedObject 时,嵌套对象的已发布属性的更改不会更新 UI,直到父对象发生某些情况。这是一个功能、一个错误(在 SwiftUI 中)还是我的代码中的一个错误?
这是一个简化的示例。单击父级的开/关按钮会立即更新 UI,但单击子级的开/关按钮不会更新,直到父级更新为止。
我正在运行 Xcode 12.5.1。
import SwiftUI
class NestedObject: NSObject, ObservableObject {
@Published var flag = false
}
class StateObject: NSObject, ObservableObject {
@Published var flag = false
@Published var nestedState = NestedObject()
}
struct ContentView: View {
@ObservedObject var state = StateObject()
var body: some View {
VStack {
HStack {
Text("Parent:")
Button(action: {
state.flag.toggle()
}, label: {
Text(state.flag ? "On" : "Off")
})
}
HStack {
Text("Child:")
Button(action: {
state.nestedState.flag.toggle()
}, label: {
Text(state.nestedState.flag ? "On" : "Off")
})
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Run Code Online (Sandbox Code Playgroud)
@ObservedObject或在更新@StateObject时更新视图ObservableObject。当@Published属性更改或直接调用时会发生这种情况objectWillChange.send()。
struct因此,“正常”(也是最简单)的方法是对属性使用值类型,例如 a @Published。
struct NestedObject {
var flag = false
}
Run Code Online (Sandbox Code Playgroud)
这样做的原因是,NestedObject当修改其属性时,整个内容都会发生变化,因为它struct是值类型。相反,当修改引用类型的属性class时,其属性不会改变(即引用保持不变)。
但是,有时您可能需要它是一个引用类型对象,因为它可能有自己的生命周期,等等......
在这种情况下,您绝对可以只调用state.objectWillChange.send(),但这仅在视图启动更改时有效,而不是在嵌套对象启动更改时有效。在我看来,这里最好的通用方法是使用具有自己的嵌套内部视图@ObservedObject来观察内部对象的变化:
struct ContentView: View {
private struct InnerView: View {
@ObservedObject var model: NestedObject
var body: some View {
Text("Child:")
Button(action: {
model.flag.toggle()
}, label: {
Text(model.flag ? "On" : "Off")
})
}
}
@StateObject var state = OuterObject() // see comments 1, 2 below
var body: some View {
VStack {
HStack {
Text("Parent:")
Button(action: {
state.flag.toggle()
}, label: {
Text(state.flag ? "On" : "Off")
})
}
HStack {
InnerView(model: state.nestedObject)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
1. 你不应该调用你的 class StateObject,因为它与StateObjectSwiftUI 的属性包装器冲突。我将其重命名为OuterObject.
2. 此外,您应该使用@StateObject而不是@ObservedObject在视图内实例化对象。
wor*_*dog -1
试试这个,对我来说在 ios-15、catalyst 15、macos 12、使用 xcode 13 上效果很好:
HStack {
Text("Child:")
Button(action: {
state.objectWillChange.send() // <--- here
state.nestedState.flag.toggle()
}, label: {
Text(state.nestedState.flag ? "On" : "Off")
})
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3669 次 |
| 最近记录: |