Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI callback as parameter to a view

Tags:

ios

swift

swiftui

I'm trying to split my SwiftUI views to as small-reusable components as possible. So I have MainView which is at the top, and then two views (MyContentView and MenuView) that both live inside MainView. Both the inner views have some functionality that I want to be updating something in the MainView. So I thought I could pass some function as a parameter to the inner views from the MainView, so when the button is pressed in the inner views it would trigger code in the MainView. The closest I managed to get to it is causing the function parameter to be triggered on every update of the inner View. What is the best way to achieve that? Here is an example of my code:

Main View:

struct MainView: View {
    var body: some View {
         VStack {
             MyContentView(self.$doSomething)
             MenuView(self.$doSomething)
         }
    }

    func doSomething() {
        print("do something")
    }
}

struct MyContentView : View {
    var doSomething : ()
    var body: some View {
        Button(action: { self.doSomething }) { Text("do something") }
    }
}

struct MenuView : View {
    var doSomething : ()
    var body: some View {
        Button(action: { self.doSomething }) { Text("Menu do something") }
    }
}

What is the best practice to be able to receive callbacks from inner views?

like image 985
Panos Avatar asked Mar 28 '20 16:03

Panos


1 Answers

Below variant works. Tested with Xcode 11.4.

struct MainView: View {
    var body: some View {
         VStack {
             MyContentView(doSomething: self.doSomething)
             MenuView(doSomething: self.doSomething)
         }
    }

    func doSomething() {
        print("do something")
    }
}

struct MyContentView : View {
    var doSomething : () -> ()
    var body: some View {
        Button(action: { self.doSomething() }) { Text("do something") }
    }
}

struct MenuView : View {
    var doSomething : () -> ()
    var body: some View {
        Button(action: { self.doSomething() }) { Text("Menu do something") }
    }
}
like image 76
Asperi Avatar answered Nov 16 '22 06:11

Asperi