My view has two Bool
conditions: condtion1
and condition2
. They can both be false, or only one true. When both conditions are false, just inherit the default accentColor
from the parent view. If condition1
is true, override the accentColor
to color1
, else if condtion2
is true, override the accentColor
to color2
.
Unfortunately, the .accentColor()
modifier doesn't seem to have any way to tell it to use the default from parent view, both these do not result in the default from parent:
.accentColor(.accentColor)
.accentColor(nil)
these two set the accentColor to blue. So a conditional modifier is needed. I came up with three ways but is there some better way? Here is my very simple sample code:
import SwiftUI
// copy from https://fivestars.blog/swiftui/conditional-modifiers.html
extension View {
@warn_unqualified_access
@ViewBuilder
func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View {
if condition {
transform(self)
} else {
self
}
}
}
struct ChildAAA: View {
let condition1: Bool
let condition2: Bool
let color1 = Color.green
let color2 = Color.yellow
var body: some View {
Button("Help Me!!!") {
}
// this works but do not like because the two if's conditions are evaluated, want short circuit if condition1 is true
.if(condition1) { $0.accentColor(color1)}
.if(condition2) { $0.accentColor(color2)}
}
}
struct ChildBBB: View {
let condition1: Bool
let condition2: Bool
let color1 = Color.green
let color2 = Color.yellow
var body: some View {
Button("Help Me!!!") {
}
// better, but harder to comprehend and `condition1` is repeated and evaluated twice
.if(condition1 || condition2) { $0.accentColor(condition1 ? color1 : color2) }
}
}
// how about add an `if` overload that take a pair of (condition, transform)?
extension View {
@warn_unqualified_access
@ViewBuilder
func `if`<Transform1: View, Transform2: View>(_ condition1: Bool, _ transform1: (Self) -> Transform1, _ condition2: () -> Bool, _ transform2: (Self) -> Transform2) -> some View {
if condition1 {
transform1(self)
} else if condition2() {
transform2(self)
} else {
self
}
}
}
struct ChildCCC: View {
let condition1: Bool
let condition2: () -> Bool
let color1 = Color.green
let color2 = Color.yellow
init(condition1: Bool, condition2: @escaping @autoclosure () -> Bool) {
self.condition1 = condition1
self.condition2 = condition2
}
var body: some View {
Button("Help Me!!!") {
}
// is this better?
// with this, condition1 and condition2 appear once, can short circuit if condition1 is true
.if(condition1, { $0.accentColor(color1) }, condition2, { $0.accentColor(color2) })
}
}
struct ContentView: View {
var body: some View {
VStack {
ChildAAA(condition1: false, condition2: false)
ChildAAA(condition1: true, condition2: false)
ChildAAA(condition1: false, condition2: true)
ChildBBB(condition1: false, condition2: false)
ChildBBB(condition1: true, condition2: false)
ChildBBB(condition1: false, condition2: true)
ChildCCC(condition1: false, condition2: false)
ChildCCC(condition1: true, condition2: false)
ChildCCC(condition1: false, condition2: true)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}