Home > database >  How to send an event from a parent view to a child view in SwiftUI
How to send an event from a parent view to a child view in SwiftUI

Time:08-20

I'm looking for a way to trigger a function in the StateObjects of child components from their parent view.

Basically, I have a screen in my app that has multiple child view structs that each have a StateObject which performs queries relevant to that component. I'm trying to find a way so that when I pull down on the scrollview parent component, I can trigger a refetch function in the StateObject of each one of the children.

Here is the structure of what I am talking about :

struct ParentView : View { 

func triggerChildRefetchFunctions() -> { 
// some logic that calls ChildView1.vm.refetchData() , ChildView2.vm.refetchData() ...
} 

 var body : some View { 
   VStack { 
      Button { triggerChildRefetchFunctions()
      ChildView1()
      ChildView2()
      ChildView3()
   }

 }

}


struct ChildView : View { 

  @StateObject var vm = ChildVM()
  var body : some View ...
}


class ChildVM : ObservableObject { 
 init() { // fetch data } 

 func refetchData() { // refetches data } 

}


I want in action in the parent view to be able to call vm.refetch() on all of its children.

Depending on the screen, there could be any number of child views each with their own state object.

All the ways I have thought of seem pretty messy. Thanks!

CodePudding user response:

you could try this broad approach, where the @StateObject var vm = ChildVM() is declared at the top level (the one source of truth), and the ChildViews all observe the changes using the passed in ChildVM, through an environmentObject.

struct ParentView : View {
    @StateObject var vm = ChildVM() // <-- here at top level

    var body : some View {
        VStack {
            Button( action: { vm.refetchData() }) { // <-- here, all ChildViews will know about it
                ChildView1()
                ChildView2()
                ChildView3()
            }
        }.environmentObject(vm) // <-- here, will pass it to all ChildViews   
    }

 }

    // similarly for ChildView2, ChildView3
    struct ChildView1 : View {
        @EnvironmentObject var vm: ChildVM  // <-- here
        
        var body: some View {
            Text("ChildView1")
        }
    }
    
    class ChildVM: ObservableObject {
        init() {
            // fetch data
        }
        func refetchData() {
            // refetches data
        }
        
    }

See also: https://developer.apple.com/documentation/swiftui/stateobject

  • Related