appModel
というEnvironmentObjectを取り込むSwiftUIビューがあります。次に、body
メソッドで値appModel.submodel.count
を読み取ります。これにより、ビューが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
に渡すことでこれを修正できますが、可能であればそうしないようにします。
ネストされたモデルは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()
}
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
}
ソリン、コンバインソリューションをありがとう。