extension Bool {
/// Convenience method to map the value of a Boolean to a specific Type.
///
/// - Parameters:
/// - ifTrue: The result when the Boolean is true
/// - ifFalse: The result when the Boolean is false
/// - Returns: Returns the result of a specific Type
func mapTo<T>(_ ifTrue:T, _ ifFalse:T ) -> T {
if self {
return ifTrue
} else {
return ifFalse
}
}
}
I added this:
extension Bool {
var asBit: Double { if self { return 1 } else { return 0 } }
}
Well, I don't have suggestion for ternary operators, what you use seem equally confusing (if not more) to me. I doubt you can get any terser than ternary operator, given that SwiftUI is sensitive to statement locations. Esp that ternary operator is literally just all information (condition, true case, false case) with 2-6 extra characters. Though some of them you could turn into ViewModifier, like
color.visible(isOn)...
given that they're probably common and have semantic.
PS
The bug you cited are two year old, it'd be interesting if someone try again given that we have new diagnostic architecture since Swift 5.2.
Personally, I'd advice against tuning animation wrt. view state. It doesn't look good (without tremendous effort) with interruptible animations.
I like the extension idea. I wouldn't name a property "asBit" when it actually is a Double. If we reasonably assume anything starting with "is" to be Bool, "asDouble" is a pretty obvious modifier. Or one could go with doubleValue, in keeping with Apples tendency in Obj-C.
Ah, that was a brain fart, apologies. I meant that you mix continuous animations (.linear) with instantaneous ones (nil). It can look quite jarring when .linear one gets interrupted nil. If, say, within the 1.5 second that you're turning it on, you turn it back off. The linear animation continues, but with the added jumping animation, it can undershoot the animation outside 0...1 boundaries (though the endpoint is always correct). It's not a big problem here since opacity is already clamped should that happens. It's more apparent for things like position:
For things that really shows/hides the view, I'd try to use transition whenever possible:
ZStack {
if isOn {
Color.green
}
}
.transition(.opacity)
.animation(.linear)
IMO it express the fact that I'm showing/hiding much better, though it's just a different style, no need to fret about it. Won't work with non-filling views though.
Although you want to use the ternary operator now, I still want to add that if someone wanted to extend Bool with a mapTo() function, they should use auto closures like this:
extension Bool {
/// Convenience method to map the value of a Boolean to a specific Type.
///
/// - Parameters:
/// - ifTrue: The result when the Boolean is true
/// - ifFalse: The result when the Boolean is false
/// - Returns: Returns the result of a specific Type
func mapTo<T>(_ ifTrue: @autoclosure () -> T, _ ifFalse: @autoclosure () -> T) -> T {
if self {
return ifTrue()
} else {
return ifFalse()
}
}
}
Only then the behavior of calling mapTo() would be exactly the same as when using the ternary operator.
Theoretically, you can use use type inference to infer the type or as to provide the type information.
let a: Int = false.numericValue
let b = true.numericValue as Double
Then again, from design perspective, I don't really like that something is inferred solely from the return type. And I don't think you should really need generic (as mentioned above).
In Swift if-else is a control flow statement, not expression. It was a point of contention some time ago, but no, if-else does not return anything.
Did you experience this on you compiler directly? If so, you should file a bug report. A statement this simple with a well-defined return type is basically nothing.
I mean, theoretically, you could use var. It's just not allowed by the language atm.
It should compile to the same code. There's no reason to write more convoluted code than necessary unless the compiler hits you with some blunt weapon.
The usual way of spelling the more general operation in SIMD and shader programming is:
func select<T>(_ ifFalse: T, _ ifTrue: T) -> T
For the specific function mapping to 0 or 1, I would personally probably call it "indicator", but "numericValue" seems acceptable as well (an indicator is explicitly a function returning 0 or 1, while some languages assign true a numeric value of -1, so there's a smidgen more ambiguity).