@Published 属性包装器不适用于 ObservableObject 的子类

thi*_*ezn 30 inheritance ios swift ios13 swiftui

我有一个符合@ObservableObject 协议的类,并从它创建了一个子类,它有自己的变量,带有@Published 属性包装器来管理状态。

使用子类时似乎忽略了@published 属性包装器。有谁知道这是否是预期行为以及是否有解决方法?

我正在运行 iOS 13 Beta 8 和 xCode Beta 6。

这是我所看到的一个例子。更新MyTestObjectText 视图上的 TextField 时,会使用 aString 值正确更新。如果我更新MyInheritedObjectTextField,则不会在 Text 视图中更新 anotherString 值。

import SwiftUI

class MyTestObject: ObservableObject {
    @Published var aString: String = ""

}

class MyInheritedObject: MyTestObject {
    @Published var anotherString: String = ""
}

struct TestObserverWithSheet: View {
    @ObservedObject var myTestObject = MyInheritedObject()
    @ObservedObject var myInheritedObject = MyInheritedObject()

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                TextField("Update aString", text: self.$myTestObject.aString)
                Text("Value of aString is: \(self.myTestObject.aString)")

                TextField("Update anotherString", text: self.$myInheritedObject.anotherString)
                Text("Value of anotherString is: \(self.myInheritedObject.anotherString)")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

thi*_*ezn 39

终于找到了这个问题的解决方案/解决方法。如果从子类中删除属性包装器,并在变量上调用基类 objectWillChange.send(),状态将正确更新。

注意:不要let objectWillChange = PassthroughSubject<Void, Never>()在子类上重新声明,因为这将再次导致状态无法正确更新。

我希望这会在未来的版本中得到修复,因为objectWillChange.send()有很多样板需要维护。

这是一个完全有效的示例:

    import SwiftUI

    class MyTestObject: ObservableObject {
        @Published var aString: String = ""

    }

    class MyInheritedObject: MyTestObject {
        // Using @Published doesn't work on a subclass
        // @Published var anotherString: String = ""

        // If you add the following to the subclass updating the state also doesn't work properly
        // let objectWillChange = PassthroughSubject<Void, Never>()

        // But if you update the value you want to maintain state 
        // of using the objectWillChange.send() method provided by the 
        // baseclass the state gets updated properly... Jaayy!
        var anotherString: String = "" {
            willSet { self.objectWillChange.send() }
        }
    }

    struct MyTestView: View {
        @ObservedObject var myTestObject = MyTestObject()
        @ObservedObject var myInheritedObject = MyInheritedObject()

        var body: some View {
            NavigationView {
                VStack(alignment: .leading) {
                    TextField("Update aString", text: self.$myTestObject.aString)
                    Text("Value of aString is: \(self.myTestObject.aString)")

                    TextField("Update anotherString", text: self.$myInheritedObject.anotherString)
                    Text("Value of anotherString is: \(self.myInheritedObject.anotherString)")
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 哦。我的。上帝。我已经花了一周的时间费尽心力,以各种方式进行重构。这。这就是问题。非常感谢!!!! (4认同)
  • 您是否将此作为错误归档?你能把雷达号码贴在这里,以便我可以欺骗吗? (3认同)
  • 要使这个答案起作用,还有另一个要求:基类至少需要一个 @Published var,否则 objectWillChange.send() 不会执行任何操作。 (3认同)
  • 该死,刚刚偶然发现了同样的问题。如果你想制作一个真正的应用程序而不是一些标题党教程,那么 SwiftUI 现在真是一团糟。 (3认同)

grg*_*grg 6

iOS 14.5 解决了这个问题。

结合

已解决的问题

在符合 ObservableObject 的类型的子类中使用 Published 现在可以正确发布更改。(71816443)