-
-
Save darrarski/f3886d4d0a3598132a3fdd62b3061eb2 to your computer and use it in GitHub Desktop.
import SwiftUI | |
func IfLet<T, ThenOut: View>( | |
_ value: T?, | |
then: (T) -> ThenOut | |
) -> some View { | |
ViewBuilder.buildIf(value.map { then($0) }) | |
} | |
func IfLet<T, ThenOut: View, ElseOut: View>( | |
_ value: T?, | |
then: (T) -> ThenOut, | |
`else`: () -> ElseOut | |
) -> some View { | |
value.map { ViewBuilder.buildEither(first: then($0)) } | |
?? ViewBuilder.buildEither(second: `else`()) | |
} |
I did some cosmetic changes to easily understand your helpful solution.
extension View {
func ifLet<Value, Then: View>(
_ value: Value?,
then: (Value) -> Then
) -> some View {
ViewBuilder.buildIf(value.map { then($0) })
}
func ifLet<Value, Then: View, Else: View>(
_ value: Value?,
then: (Value) -> Then,
else: () -> Else
) -> some View {
value.map { ViewBuilder.buildEither(first: then($0)) }
?? ViewBuilder.buildEither(second: `else`())
}
}
struct TestView: View {
var test: String?
var body: some View {
Group {
ifLet(test) { Text($0) }
ifLet(test, then: { Text($0) }, else: { Text("Empty") })
}
}
}
@filimo Thanks! I don’t think extending View
is a good idea. It looks really nice in your example, but it also allows writing such code:
var test: String? = nil
...
Text(“Hello, World!”).ifLet(test) { Test($0) }
Which doesn’t feel right to me. Text(“Hello, World!”)
will be ignored permanently, no matter if test
is nil
or has a value. Such code should not compile in my opinion.
@filimo Thanks! I don’t think extending View is a good idea.
I second this, unless this is implemented differently.
extension View {
@ViewBuilder
func showWhen(_ condition: Bool) -> some View {
if condition {
self
}
}
}
This would allow you to wrap the whole view with all its modifiers into an Optional
.
I got it. I saw this case in PureSwiftUI here
@State private var toggle = false
//...
// using RenderIf
var body: some View {
RenderIf(toggle) {
Text("It's true")
}.elseRender {
SFSymbol(.nosign)
}
}
@filimo Thanks! I don’t think extending
View
is a good idea. It looks really nice in your example, but it also allows writing such code:var test: String? = nil ... Text(“Hello, World!”).ifLet(test) { Test($0) }Which doesn’t feel right to me.
Text(“Hello, World!”)
will be ignored permanently, no matter iftest
isnil
or has a value. Such code should not compile in my opinion.
it can be done with modifierIf
struct HideView: ViewModifier {
func body(content: Content) -> some View {
content.hidden()
}
}
struct ModifierIfDemo: View {
var hide: Bool? = nil
var body: some View {
Text("Hello, World!").modifierIf(hide ?? false, HideView())
}
}
one more way
func ifLet<T, V>(_ value: T?, then: (T) -> V) -> V? where V: View {
value.map(then)
}
let optionalString: String? = "swift"
var body: some View {
optionalString.map { string in
Text(string)
}
}
Which is a quote of my code from here :P https://forums.swift.org/t/how-to-set-default-clouse-param-in-view-method/33815/5
Oops, I didn't notice))
This extension can help to use short and long methods but I can notice
_ConditionalContent
is unofficial and might be changed or removed in the future.