iOS SwiftUI: Data Flow Flow in Subviews @ObservedObject

Viewed 2174

I'm having a problem of updates in my application. I can't understand very well what is going on with the data flow between the subviews.

This is my current structure

  • ViewModel: ObsebsrvableObject

  • MainView with ObservedObject (viewModel)

    • ChildView with a list from MainView observed object (just the list is passed as a normal array - not bindable)
      • NephewView with the list passed to the childView, still as a normal array

What is happening:

Every time I modify the list, the MainView updates triggering a new rebuild of ChildView, but the NephewView does not update

What I would like to have:

I would like to update the Main, the Child and the NephewView views every time the observedObject get an update

Problem:

I can't understand why if the Child View rebuild, the nephew doesn't.

Example Code

class ViewModel: ObservableObject {

    let userData = UserData.shared

    var canceller: AnyCancellable?

    @Published var items: [Items]


    init() {
      items = []
      canceller = userData.objectWillChange
        .throttle(for: 5, scheduler: RunLoop.main, latest: true)
        .sink(receiveCompletion: { data  in
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.items = data.items
            }
        },
        receiveValue: { _ in
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.items = data.items
            }
        })
   }
 }

struct MainView: View {

  @ObservedObject var model = ViewModel()


  var body: some View {
      ChildView(items: model.items)
  }
}

struct ChildView: View {

  let items: [Items]


  var body: some View {
      NephewView(items: items)
  }
}

struct NephewView: View {

  let items: [Items]

  var body: some View {
      List...
  }
}

The sink works properly, it's just the UI part that does not get updates. Maybe the way I'm updating the publisher is wrong?

1 Answers

Your MainView

 ChildView(items: $model.items)

Your ChildView

struct ChildView: View {
  @Binding let items: [Items]
  var body: some View {
     List { 
     ForEach(self.items) { item in
           NephewView(items: item)
          }
        }
      }
    }

Your NephewView

struct NephewView: View {
  @Binding let items: item

  var body: some View {
    // Your view logic goes here with single item
  }
}

Related