I am working on a SwiftUI project. I've created a custom button that I can pass a function to. This looks like the following.
Custom Button
struct CustomButton: View {
let buttonTitle: String
var function: () -> Void
var body: some View {
Button(action: {
self.function()
}, label: {
Text(self.buttonTitle)
}) // Button - Login
} // View
}
In the view that uses this I can do the following.
struct NewView: View {
var body: some View {
CustomButton(buttonTitle: "Custom Button", function: myFunc)
}
}
func myFunc() {
print("My Custom Button Tapped")
}
This works really well.
What I want to do now is pass a parameter to the function. And I am having trouble with this. I tried the following.
struct CustomButton: View {
let buttonTitle: String
var function: (String) -> Void
var body: some View {
Button(action: {
self.function() // I DON'T KNOW WHAT DO TO HERE.
}, label: {
Text(self.buttonTitle)
}) // Button - Login
} // View
}
struct NewView: View {
var body: some View {
CustomButton(buttonTitle: "Custom Button", function: myFunc(text: "Hello"))
}
}
func myFunc(text: String) {
print(text)
}
This does not work. When I call CustomButton I get the following error.
Cannot convert value of type '()' to expected argument type '() -> Void'
I also do not know what parameter to add to the self.function() call in the Button action.
Any help would be greatly appreciated.
CodePudding user response:
First, the simplest answer -- by enclosing myFunc(text: "Hello")
in { }
, you can turn it into a closure. Then, it can get passed to your original () -> Void
declaration.
struct CustomButton: View {
let buttonTitle: String
let function : () -> Void
var body: some View {
Button(action: {
self.function()
}, label: {
Text(self.buttonTitle)
}) // Button - Login
} // View
}
struct NewView: View {
var body: some View {
CustomButton(buttonTitle: "Custom Button", function: {
myFunc(text: "Hello")
})
}
}
You could also use an @autoclosure
to provide similar behavior without the { }
, but you'd have to declare a custom init
for your CustomButton
:
struct CustomButton: View {
let buttonTitle: String
let function : () -> Void
init(buttonTitle: String, function: @autoclosure @escaping () -> Void) {
self.buttonTitle = buttonTitle
self.function = function
}
var body: some View {
Button(action: {
self.function()
}, label: {
Text(self.buttonTitle)
}) // Button - Login
} // View
}
struct NewView: View {
var body: some View {
CustomButton(buttonTitle: "Custom Button", function: myFunc(text:"Hello"))
}
}
Finally, another option (that I think there's unlikely to a use case for, but just in case it fits) would be to pass the string parameter separately:
struct CustomButton: View {
let buttonTitle: String
let stringParameter : String
let function : (String) -> Void
var body: some View {
Button(action: {
self.function(stringParameter)
}, label: {
Text(self.buttonTitle)
}) // Button - Login
} // View
}
struct NewView: View {
var body: some View {
CustomButton(buttonTitle: "Custom Button", stringParameter: "Hello", function: myFunc)
}
}
CodePudding user response:
Here what you may looking for:
struct ContentView: View {
let action: (String) -> Void = { value in print(value) }
var body: some View {
CustomButtonView(string: "print", valueToSend: "Hello World!", action: action)
}
}
struct CustomButtonView: View {
let string: String
let valueToSend: String
let action: (String) -> Void
var body: some View {
Button(string) {
action(valueToSend)
}
}
}