Home > other >  SwiftUI Generics in reduce function on some View
SwiftUI Generics in reduce function on some View

Time:10-22

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 ViewProtocol (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.).

  • Related