Reputation: 1111
I have 2 custom button styles and I want to change the style when I tap the button. I tried this way:
Button(action: {
self.pressed.toggle()
})
{
Text("Button")
}.buttonStyle(pressed ? style1() : style2())
But it is not working, it is giving me an error from the VStack that it belongs to:
Unable to infer complex closure return type; add explicit type to disambiguate
If I do something like:
.buttonStyle(style1())
Or
.buttonStyle(style2())
Then the error goes away, so it's not from style1() or style2().
Upvotes: 17
Views: 7103
Reputation: 5152
You can write an extension on View
to apply different modifiers conditionally based on a boolean condition. This can be useful when you want to customize the appearance or behavior of a view based on some state.
First, make sure you have the following extension defined:
extension View {
@ViewBuilder
func `if`<TrueContent: View, FalseContent: View>(
_ condition: Bool,
if ifTransform: (Self) -> TrueContent,
else elseTransform: (Self) -> FalseContent
) -> some View {
if condition {
ifTransform(self)
} else {
elseTransform(self)
}
}
}
With this extension, you can apply condition-based modifiers to views. Let's take the example of a Button
from the question:
Button {
print("👋👋👋")
} label: {
Text("Hello World!")
}
.if(vm.status == .subscribed, if: { button in
button.buttonStyle(TertiaryButton())
}, else: { button in
button.buttonStyle(SecondaryButton())
})
Upvotes: 5
Reputation: 257693
It's swift type-checking violation... I would recommend instead
Button(action: {
self.pressed.toggle()
})
{
Text("Button")
}.buttonStyle(Your_style(condition: pressed)) // << put conditional styling inside
See for example solution in Change buttonStyle Modifier based on light or dark mode in SwiftUI
Upvotes: 4
Reputation: 2067
You can create a useful extension like below
extension View {
func conditionalModifier<M1: ViewModifier, M2: ViewModifier>
(on condition: Bool, trueCase: M1, falseCase: M2) -> some View {
Group {
if condition {
self.modifier(trueCase)
} else {
self.modifier(falseCase)
}
}
}
func conditionalModifier<M: ViewModifier>
(on condition: Bool, trueCase: M) -> some View {
Group {
if condition {
self.modifier(trueCase)
}
}
}
}
Usage;
@State var condition = false
var body: some View {
Text("conditional modifier")
// Apply style if condition is true, otherwise do nothing
.conditionalModifier(on: condition, trueCase: Style1())
// Decision between 2 style
.conditionalModifier(on: condition, trueCase: Style1(), falseCase: Style2())
}
Upvotes: 1