Unable to infer complex closure return type; Issue in nesting ForEach inside a Zstack

Hello!

I'm trying to Make a custom viewModifier which will add a defined number of shape views on a card based on a parameter. To do this, I'm using a VStack which in itself is nested inside a Zstack. But for some reason I get a "Unable to infer complex closure return type; add explicit type to disambiguate" error.

Below is the body function of the viewModifier

import SwiftUI

struct addShape: ViewModifier{
    var shapeType: CardShape
    var shadingType: Double
    var shapeColor: Color
    var size: CGSize
    var noOfShapes: Int
    
    func body(content: Content) -> some View{
        ZStack{
            VStack{
                ForEach(1..<noOfShapes, id: \.self){
                    Group{
                        if (shapeType == .rectangle){
                            RoundedRectangle(cornerRadius: radiusValue)
                                .fill(shapeColor)
                                .opacity(shadingType)
                            RoundedRectangle(cornerRadius: radiusValue)
                                .stroke(lineWidth: strokeWidth)
                        }
                        else if (shapeType == .oval){
                            Ellipse()
                                .fill(shapeColor)
                                .opacity(shadingType)
                            Ellipse()
                                .stroke(lineWidth: strokeWidth)
                        }
                        else {
                            RoundedRectangle(cornerRadius: radiusValue)
                                .fill(shapeColor)
                                .opacity(shadingType)
                            RoundedRectangle(cornerRadius: radiusValue)
                                .stroke(lineWidth: strokeWidth)
                        }
                    }
                    .frame(width: (size.width)/CGFloat(noOfShapes+1), height: (size.height)/CGFloat(noOfShapes+1), alignment: .center)
                    .foregroundColor(shapeColor)
                }
            }
            content
        }
    }
    let strokeWidth: CGFloat = 2
    let radiusValue: CGFloat = 8
}

Where am I going wrong?

ForEach takes an @escaping closure with 1 argument. Since you're not using $0 anywhere, the compiler thinks you're supplying closure with 0 argument and is confused. If you really are not using the loop number, you can just do:

ForEach(1..<noOfShapes, id: \.self) { _ in
  ...
}

Though I think you might be mixing up some logic.

Another, since the closure is escape, all properties you used inside it needs to be explicitly marked as escape*, or use self.. That is, if you're using shapeType, shadingType, shapeColor, size, noOfShapes, strokeWidth, radiusValue inside that closure, you need to say self.shapeType, self.shadingType, etc. Or you can add it to the capture list:

ForEach(...) { [shapeType = self.shapeType] _ in
}

Though note that values in the capture list is just a copy of the original data.

It's actually amazing that you can type all that before hitting both of these errors.

* After SE-0269, ie, after Swift 5.3, you can omit self. if self is a value type (struct, enum), or if you simply capture self.

PS

Here are some resources about escaping closure and shorthand argument name.

1 Like

Thank you so much! I was wondering how can I use ForEach without using the closure argument, didn't really think about using the underscore. I also realised there has to be another ZStack capturing the if-else tree.