swiftui - 嵌套 ObservedObject 中的更改不会更新 UI
问题描述
当我有一个嵌套的 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()
}
}
解决方案
@ObservedObject
或@StateObject
在更新时更新视图ObservableObject
。这发生在@Published
更改属性或直接调用objectWillChange.send()
.
因此,“正常”(也是最简单的)方法是对属性使用值类型,例如struct
a @Published
。
struct NestedObject {
var flag = false
}
这样做的原因是,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)
}
}
}
}
1. 你不应该调用你的类StateObject
,因为它与StateObject
SwiftUI 的属性包装器冲突。我将其重命名为OuterObject
.
2. 此外,如果您在视图中实例化对象,您应该使用@StateObject
而不是。@ObservedObject
推荐阅读
- javascript - 告诉页面通过锚点聚焦元素的事实上的方式是什么?
- react-native - 拥有图像@2x @3x 与只有一张高分辨率图像
- r - 如何根据一列中的值更新多行重复?
- entity-framework-core - EF Core 无法确定“ICollection”类型的导航属性“Colour.ColourGroups”表示的关系
' - c# - 如何使用异步等待处理外部事件?
- here-api - 如何重新定位地图中心以适应信息泡泡?
- angular - 如何通过复选框发布对象数组
- php - Failed loading cafile stream in "file_get_contents()"?
- c# - 返回单个类型或类型列表?
- python - python自动重采样数据