filimo
(VictorK)
February 14, 2020, 10:00am
1
I tried to set else
default param in ifLet
method but I face an error: Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
. What did wrong?
extension View {
func ifLet<Value, Then: View, Else: View>(
_ value: Value?,
then: (Value) -> Then,
else: () -> Else = { EmptyView() }
) -> _ConditionalContent<Then, Else> {
if let value = value {
return ViewBuilder.buildEither(first: then(value))
} else {
return 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") })
}
}
}
I think it should be else: () -> Else
.
filimo
(VictorK)
February 15, 2020, 4:13am
3
Sorry, I did mistake in my question but my question was about how to set default value of else
param.
filimo
(VictorK)
February 15, 2020, 4:22am
4
Stackoverflow guy offers to use two methods. Optional else
impossible?
extension View {
func ifLet<Value, Then: View>(
_ value: Value?,
then: (Value) -> Then
) -> _ConditionalContent<Then, EmptyView> {
if let value = value {
return ViewBuilder.buildEither(first: then(value))
} else {
return ViewBuilder.buildEither(second: EmptyView())
}
}
func ifLet<Value, Then: View, Else: View>(
_ value: Value?,
then: (Value) -> Then,
else: () -> Else
) -> _ConditionalContent<Then, Else> {
if let value = value {
return ViewBuilder.buildEither(first: then(value))
} else {
return ViewBuilder.buildEither(second: `else`())
}
}
}
It's possible, just use Optional
instead of _ConditionalContent
.
Here is your correct overload:
func ifLet<T, V>(_ value: T?, then: (T) -> V) -> V? where V: View {
value.map(then)
}
And as you can see, you can just use map
from Optional
to produce your view.
// quick example
let optionalString: String? = "swift"
var body: some View {
optionalString.map { string in
Text(string)
}
}
Optional
conditionally conforms to View
when Wrapped
conforms to View
.
1 Like