ネストされたObservableObjectsにバインドするようにSwiftUIビューに指示する方法


18

と呼ばれるEnvironmentObjectを取り込むSwiftUIビューがありますappModel。次にappModel.submodel.count、そのbodyメソッドで値を読み取ります。これにより、ビューがプロパティcountにバインドされsubmodel、プロパティが更新されたときに再レンダリングされることが期待されますが、これは発生しないようです。

これはバグですか?そうでなければ、SwiftUIで環境オブジェクトのネストされたプロパティにビューをバインドする慣用的な方法は何ですか?

具体的には、私のモデルは次のようになります...

class Submodel: ObservableObject {
  @Published var count = 0
}

class AppModel: ObservableObject {
  @Published var submodel: Submodel = Submodel()
}

そして私の見解はこのように見えます...

struct ContentView: View {
  @EnvironmentObject var appModel: AppModel

  var body: some View {
    Text("Count: \(appModel.submodel.count)")
      .onTapGesture {
        self.appModel.submodel.count += 1
      }
  }
}

アプリを実行してラベルをクリックすると、countプロパティは増加しますが、ラベルは更新されません。

これをappModel.submodelプロパティとしてに渡すことで修正できますがContentView、できれば避けたいと思います。


私もこのようにアプリを設計しています。私は通常、過去のアプリ開発でグローバルAppオブジェクトを持っています。このスーパー "App"クラスの設計は、環境変数が標準的なプラクティスになると誰もが考えていますか?複数のEnvironmentObjectsの使用も検討していましたが、それを維持するのは困難でした。
Michael Ozeryansky、

回答:


22

ネストされたモデルはSwiftUIではまだ機能しませんが、次のようなことができます

class Submodel: ObservableObject {
    @Published var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: Submodel = Submodel()

    var anyCancellable: AnyCancellable? = nil

    init() {
        anyCancellable = submodel.objectWillChange.sink { (_) in
            self.objectWillChange.send()
        }
    } 
}

基本的にAppModelは、イベントをキャッチしSubmodelて、ビューにさらに送信します

編集:

SubModelクラスである必要がない場合は、次のいずれかを試すことができます。

struct Submodel{
    var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: Submodel = Submodel()
}

ありがとう、これは役に立ちます!「ネストされたモデルがSwiftUIでまだ機能しない」と言うとき、それらが計画されていることを確実に知っていますか?
rjkaplan

よくわかりませんが、私の意見ではうまくいくはずです。プロジェクトでも同様の方法を使用します。そのため、より良いアプローチが見つかれば、編集を加えます
Sorin Lica

@SorinLica タイプである必要SubmodelがありObservableObject ますか?
Farhan Amjad

うまくいきました!素晴らしいソリューション!
Md Shahed Hossain

1

3つのViewModelはすべて通信および更新できます

// First ViewModel
class FirstViewModel: ObservableObject {
var facadeViewModel: FacadeViewModels

facadeViewModel.firstViewModelUpdateSecondViewModel()
}

// Second ViewModel
class SecondViewModel: ObservableObject {

}

// FacadeViewModels Combine Both 

import Combine // so you can update thru nested Observable Objects

class FacadeViewModels: ObservableObject { 
lazy var firstViewModel: FirstViewModel = FirstViewModel(facadeViewModel: self)
  @Published var secondViewModel = secondViewModel()
}

var anyCancellable = Set<AnyCancellable>()

init() {
firstViewModel.objectWillChange.sink {
            self.objectWillChange.send()
        }.store(in: &anyCancellable)

secondViewModel.objectWillChange.sink {
            self.objectWillChange.send()
        }.store(in: &anyCancellable)
}

func firstViewModelUpdateSecondViewModel() {
     //Change something on secondViewModel
secondViewModel
}

ソリン、コンバインソリューションをありがとう。


コードを更新できますか?多くのコンパイラエラーがある
DevB2F

-2

バグのようです。xcodeを最新バージョンに更新すると、ネストされたObservableObjectsにバインドするときに正しく動作します


現在使用しているxcodeのバージョンがどのように機能するかを説明できますか 現在Xcode 11.0を使用していますが、この問題が発生します。11.1へのアップグレードで問題が発生しましたが、80%は完了しません。
Michael Ozeryansky
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.