简体   繁体   中英

"compiler is unable to type-check this expression" — how to rewrite this basic expression?

Before someone flags this as "SO is not a code writing service"... please read my post fully and see all the possible solutions I have tried to fix my problem:

I am trying to use a ForEach loop to create cutout circle masks, to look like a perforated edge. I get this error:

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

I have encountered this error before, and it's usually straightforward to do as it says and break the expression up. This time, I can't figure out a way to solve it.

I believe the issue is caused by the padding on the Circle with the holePunchSize (and various alternatives). It works fine if I use a fixed value. Originally I had the multiplier expression right in the.padding — ((geo.size.width - 40) / 17) * 2.3 . Then I thought to calculate the value once in an .onAppear and use that ( holePunchSize ). Then I thought, maybe I have to split the expression further, the result you can see in the .onAppear below.

Still, I get the error. I have no idea how I can possibly break this down any more.

Also, I have tried to simplify this further just for testing, by using fixed values in the .frame(width.. , and all but one of the .padding , it still complains.

Code:

.reverseMaskBottomLeading {
    ForEach(0..<17) { i in
        Circle()
            .frame(width: (geo.size.width - 40) / 17, alignment: .bottomLeading)
            .padding([.bottom], -14)
            .padding([.leading], i * (geo.size.width - 40) )
            .padding([.leading], CGFloat((i * (holePunchSize))))
            .padding([.leading], -12)
    }
    .padding([.leading, .trailing])
}
.onAppear {
    holePunchSize = geo.size.width - 40
    holePunchSize = holePunchSize / 17
    holePunchSize = holePunchSize * 2.3
}


...


@inlinable
public func reverseMaskBottomLeading<Mask: View>(
    alignment: Alignment = .bottomLeading,
    @ViewBuilder _ mask: () -> Mask
) -> some View {
    self.mask {
        Rectangle()
            .overlay(alignment: alignment) {
                mask()
                    .blendMode(.destinationOut)
            }
    }
}

Swift doesn't support binary arithmetic operators like + and * with operands of different types. The only exception is that Swift will convert between CGFloat and Double automatically.

For example, in the code you posted, i * (geo.size.width - 40) is not legal, because i is Int while geo.size.width - 40 is CGFloat .

Note that integer literals like 40 can be treated as a variety of types depending on context; here, if the errors are corrected, it will be treated as CGFloat to make the - operator work. However, when there are errors around, Swift can end up trying lots of different types for each integer literal, which means lots of different combinations, and so it can time out. Your Circle expression has five integer literals, so if Swift can treat each as any of, let's say, 12 different types, then there are 12⁵ = 248,832 type combinations it could try. Swift has optimizations to reduce this number, but it's still exponential.

Anyway, I see at least two cases where you are trying to multiply Int by CGFloat :

            .padding([.leading], i * (geo.size.width - 40) )
                                   ↑
                                   here

and

            .padding([.leading], CGFloat((i * (holePunchSize))))
                                            ↑
                                            here

You need to convert i to CGFloat in both places:

            .padding([.leading], CGFloat(i) * (geo.size.width - 40))
            .padding([.leading], CGFloat(i) * holePunchSize)

Also, you might want to consider using a Canvas to draw your reverseMaskBottomLeading instead of that modifier-heavy ForEach / Circle combination.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM