buttonswiftui

SwiftUI - Button - How to pass a function request to parent


How can I have a button perform an action which triggers a function in its 'parent' view? I'm trying to refactor my code so that components are as small as possible.

In this case, the button performs a few tasks, but one of them is to run a function:

Button(
 action: {
  self.setViewBackToNil()
 }){
  Text("Button")
}

// which triggers a function
func setViewBackToNil(){
 self.userData.image = nil
 self.isProcessing = false
 .... etc
}

Now, if I turn the button into its own view, I can't pass self.setViewBackToNil because it's contained within the struct of the parent.

Is there a way for a component to trigger a function within its parent?


Solution

  • The best examples on closures and how they can be used is found in the official swift documentation.

    This is a small example on how to pass a closure to your child view which then calls a function of the parent:

    struct ChildView: View {
        var function: () -> Void
        
        var body: some View {
            Button(action: {
                self.function()
            }, label: {
                Text("Button")
            })
        }
    }
    
    struct ParentView: View {
        var body: some View {
            ChildView(function: { self.fuctionCalledInPassedClosure() })
        }
        
        func fuctionCalledInPassedClosure() {
            print("I am the parent")
        }
    }
    

    I hope this helps!

    Pass a function

    And here is an example to pass the function:

    struct ChildView: View {
        var function: () -> Void
        
        var body: some View {
            Button(action: {
                self.function()
            }, label: {
                Text("Button")
            })
        }
    }
    
    struct ParentView: View {
        var body: some View {
            ChildView(function: self.passedFunction)
        }
        
        func passedFunction() {
            print("I am the parent")
        }
    }
    

    Pass a function with parameters

    struct ChildView: View {
        var myFunctionWithParameters: (String, Int) -> Void
        
        var body: some View {
            Button(action: {
                self.myFunctionWithParameters("parameter", 1)
            }, label: {
                Text("Button")
            })
        }
    }
    
    struct ParentView: View {
        var body: some View {
            ChildView(myFunctionWithParameters: self.passedFunction)
        }
        
        func passedFunction(myFirstParameter: String, mySecondParameter: Int) {
            print("I am the parent")
        }
    }