I want to write a View extension, that applies multiple shadow effects on the current view. For that I want to use the reduce function on the array of given shadow configs.
My Code looks like this:
func shadowEffects(_ shadowConfigs: [Double]) -> some View {
shadowConfigs.reduce(self) { currentView, shadowConfig in
currentView.shadow(
color: .red,
radius: shadowConfig
)
}
}
But this causes a Cannot convert value of type 'some View' to closure result type 'Self'.
I could fix this wrapping it in AnyView but that does not seem like a good solution for me. As I always deal with the same type.
func shadowEffects(_ shadowConfigs: [Double]) -> some View {
shadowConfigs.reduce(AnyView(self)) { currentView, shadowConfig in
AnyView(currentView.shadow(
color: .red,
radius: shadowConfig
))
}
}
What alternatives do I have?
CodePudding user response:
The problem is that when you declare a method to return some View
, it needs to know at compile time the actual concrete return type that adopts the View
Protocol (e.g. Text, Button, Vstack etc.). In your example the self
in your mehtod is of type View
that is a Protocol, so the compiler can not determine the concrete type and hence the error.
Unfortunately there are not simple solutions. The first is to use type erasure utilizing the AnyView
as you did. Since AnyView
is a actual entity the compiler can resolve the underlying return type. The second is to add you extension to directly to each of the adopters of the View protocol (Text, Button, Vstack etc.).