How to tell SwiftUI views to bind to nested ObservableObjects How to tell SwiftUI views to bind to nested ObservableObjects ios ios

How to tell SwiftUI views to bind to nested ObservableObjects


Nested models does not work yet in SwiftUI, but you could do something like this

class SubModel: ObservableObject {    @Published var count = 0}class AppModel: ObservableObject {    @Published var submodel: SubModel = SubModel()        var anyCancellable: AnyCancellable? = nil        init() {        anyCancellable = submodel.objectWillChange.sink { [weak self] (_) in            self?.objectWillChange.send()        }    } }

Basically your AppModel catches the event from SubModel and send it further to the View.

Edit:

If you do not need SubModel to be class, then you could try something like this either:

struct SubModel{    var count = 0}class AppModel: ObservableObject {    @Published var submodel: SubModel = SubModel()}


Sorin Lica's solution can solve the problem but this will result in code smell when dealing with complicated views.

What seems to better advice is to look closely at your views, and revise them to make more, and more targeted views. Structure your views so that each view displays a single level of the object structure, matching views to the classes that conform to ObservableObject. In the case above, you could make a view for displaying Submodel (or even several views) that display's the property from it that you want show. Pass the property element to that view, and let it track the publisher chain for you.

struct SubView: View {  @ObservableObject var submodel: Submodel  var body: some View {      Text("Count: \(submodel.count)")      .onTapGesture {        self.submodel.count += 1      }  }}struct ContentView: View {  @EnvironmentObject var appModel: AppModel  var body: some View {    SubView(submodel: appModel.submodel)  }}

This pattern implies making more, smaller, and focused views, and lets the engine inside SwiftUI do the relevant tracking. Then you don't have to deal with the book keeping, and your views potentially get quite a bit simpler as well.

You can check for more detail in this post: https://rhonabwy.com/2021/02/13/nested-observable-objects-in-swiftui/


All three ViewModels can communicate and update

// First ViewModelclass FirstViewModel: ObservableObject {var facadeViewModel: FacadeViewModelsfacadeViewModel.firstViewModelUpdateSecondViewModel()}// Second ViewModelclass SecondViewModel: ObservableObject {}// FacadeViewModels Combine Both import Combine // so you can update thru nested Observable Objectsclass 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 secondViewModelsecondViewModel}

Thank you Sorin for Combine solution.