web-dev-qa-db-ja.com

@publishedプロパティラッパーObservableObjectのサブクラスで動作していません

私は@ObServableObjectプロトコルに準拠したクラスを持っており、@publishedプロパティラッパーを使用して@publishedプロパティラッパーを使用してサブクラスを作成しました。

サブクラスを使用すると、@publishedプロパティラッパーは無視されます。これが予想されるかどうか、そして回避策があるならば誰もが知っていますか?

私はiOS 13ベータ8とXcode Beta 6を実行しています。

これが私が見るものの例です。 TextFieldをMyTestObjectに更新するときは、テキストビューは揃え値で正しく更新されます。 MyInheritedObjecttextfieldを更新した場合、antherstring値はテキストビューで更新されません。

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)")
            }
        }
    }
}
 _
24
thiezn

私が見つけたこの問題に対する最善の解決策は次のとおりです。

BaseObservableObject発行者を使用してobjectWillChangeを宣言します。

_open class BaseObservableObject: ObservableObject {
    
    public let objectWillChange = ObservableObjectPublisher()

}
_

次に、サブクラスのobjectWillChangeをトリガするには、観測可能クラスと値の種類の両方に変更を処理する必要があります。

_class MyState: BaseObservableObject {

    var classVar = SomeObservableClass()
    var typeVar: Bool = false {
        willSet { objectWillChange.send() }
    }
    var someOtherTypeVar: String = "no observation for this"

    var cancellables = Set<AnyCancellable>()

    init() {
        classVar.objectWillChange // manual observation necessary
            .sink(receiveValue: { [weak self] _ in
                self?.objectWillChange.send()
            })
            .store(in: &cancellables)
    }
}
_

それからあなたはサブクラス化を続け、必要に応じて監視を追加することができます。

_class SubState: MyState {

    var subVar: Bool = false {
        willSet { objectWillChange.send() }
    }

}
_

そのクラスが既に_@Published_変数を含んでいる場合、プロキシが合成されると、ルート親クラスのBaseObservableObjectを継承することができます。しかし、ルート親クラスから最後の_@Published_値を削除すると、サブクラスのすべてのobjectWillChange.send()が静かに動作を停止します。

将来変数を追加すると、観察を追加することを忘れるのは非常に簡単なので、これらのステップを経ても残念です。うまくいけば、私たちはより良い公式修正を受けるでしょう。

0
Oskar