SwiftUI继承ObservableObject时不触发视图刷新
View refreshing not triggered when ObservableObject is inherited in SwiftUI
ContentView2
视图在model.value
变化时不刷新,如果Model
直接符合ObservableObject
而不是继承SuperModel
则可以正常工作
class SuperModel: ObservableObject {
}
class Model: SuperModel {
@Published var value = ""
}
struct ContentView2: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
Text(model.value)
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
}
}
}
使用 ObjectWillChange 解决指定的问题。
这是工作代码:
import SwiftUI
class SuperModel: ObservableObject {
}
class Model: SuperModel {
var value: String = "" {
willSet { self.objectWillChange.send() }
}
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
Text("Model Value1: \(model.value)")
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
Text("Model Value2: \(model.value)")
}
}
}
这看起来确实是个严重的缺陷。
class SuperModel: ObservableObject {
}
class Model: SuperModel {
@Published var value = ""
}
我看到 value
已更改并按预期保留新的,但 DynamicProperty
功能不起作用
以下变体对我有用 (Xcode 11.2 / iOS 13.2)
class SuperModel: ObservableObject {
@Published private var stub = "" // << required !!!
}
class Model: SuperModel {
@Published var value = "" {
willSet { self.objectWillChange.send() } // < works only if above
}
}
也可以考虑这种情况:
class SuperModel {
}
class Model: SuperModel, ObservableObject {
@Published var value = ""
}
这是您示例的工作变体。看到要能够工作,不仅需要链接发布者,而且至少需要一个 Published 属性。左右,它在某些情况下可能会有所帮助。
import SwiftUI
class SuperModel: ObservableObject {
// this is workaround but not real trouble.
// without any value in supermodel there is no real usage of SuperModel at all
@Published var superFlag = false
}
class Model: SuperModel {
@Published var value = ""
override init() {
super.init()
_ = self.objectWillChange.append(super.objectWillChange)
}
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
Text(model.value)
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
将代码更改为
var body: some View {
VStack {
Text(model.value)
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
Text(model.superFlag.description)
Button("change super flag") {
self.model.superFlag.toggle()
}
}
}
你可以看到如何同时使用你的超模
ContentView2
视图在model.value
变化时不刷新,如果Model
直接符合ObservableObject
而不是继承SuperModel
则可以正常工作
class SuperModel: ObservableObject {
}
class Model: SuperModel {
@Published var value = ""
}
struct ContentView2: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
Text(model.value)
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
}
}
}
使用 ObjectWillChange 解决指定的问题。
这是工作代码:
import SwiftUI
class SuperModel: ObservableObject {
}
class Model: SuperModel {
var value: String = "" {
willSet { self.objectWillChange.send() }
}
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
Text("Model Value1: \(model.value)")
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
Text("Model Value2: \(model.value)")
}
}
}
这看起来确实是个严重的缺陷。
class SuperModel: ObservableObject { } class Model: SuperModel { @Published var value = "" }
我看到 value
已更改并按预期保留新的,但 DynamicProperty
功能不起作用
以下变体对我有用 (Xcode 11.2 / iOS 13.2)
class SuperModel: ObservableObject {
@Published private var stub = "" // << required !!!
}
class Model: SuperModel {
@Published var value = "" {
willSet { self.objectWillChange.send() } // < works only if above
}
}
也可以考虑这种情况:
class SuperModel {
}
class Model: SuperModel, ObservableObject {
@Published var value = ""
}
这是您示例的工作变体。看到要能够工作,不仅需要链接发布者,而且至少需要一个 Published 属性。左右,它在某些情况下可能会有所帮助。
import SwiftUI
class SuperModel: ObservableObject {
// this is workaround but not real trouble.
// without any value in supermodel there is no real usage of SuperModel at all
@Published var superFlag = false
}
class Model: SuperModel {
@Published var value = ""
override init() {
super.init()
_ = self.objectWillChange.append(super.objectWillChange)
}
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
Text(model.value)
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
将代码更改为
var body: some View {
VStack {
Text(model.value)
Button("change value") {
self.model.value = "\(Int.random(in: 1...10))"
}
Text(model.superFlag.description)
Button("change super flag") {
self.model.superFlag.toggle()
}
}
}
你可以看到如何同时使用你的超模