swift “编译器无法对此表达式进行类型检查”-如何重写此基本表达式?

p5cysglq  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(132)

在有人将此标记为"SO不是代码编写服务"之前...请完整阅读我的帖子,看看我试图修复我的问题的所有可能的解决方案:
我尝试使用一个ForEach循环来创建一个镂空的圆形蒙版,看起来像一个穿孔的边缘。我得到这个错误:
编译器无法在合理的时间内对此表达式进行类型检查;尝试将表达式分解为不同的子表达式
我以前遇到过这个错误,通常都是直接按照它说的去做,把表达式拆了,这次我想不出解决的办法。
我认为该问题是由使用holePunchSize填充圆圈引起的(以及各种替代方法)。如果使用固定值,效果会很好。最初我在. padding-((geo.size.width - 40) / 17) * 2.3中有乘法器表达式。然后我想在.onAppear中计算一次值并使用它(holePunchSize)。然后我想,也许我必须进一步拆分表达式,结果可以在下面的.onAppear中看到。
尽管如此,我还是得到了错误。我不知道我怎么才能再分解这个。
此外,我还试图进一步简化这一点,只是为了测试,通过使用固定值的.frame(width..,和所有,但一个.padding,它仍然抱怨。
代码:

.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)
            }
    }
}
anauzrmj

anauzrmj1#

Swift不支持+*这类操作数类型不同的二进制算术运算符,唯一的例外是Swift会自动在CGFloatDouble之间进行转换。
例如,在您发布的代码中,i * (geo.size.width - 40)是不法律的的,因为iInt,而geo.size.width - 40CGFloat
注意,像40这样的整数字面值可以根据上下文被视为各种类型;在这里,如果错误得到纠正,它将被视为CGFloat,以使-运算符工作。但是,当周围有错误时,Swift可能最终会为每个整型文字尝试许多不同的类型,这意味着许多不同的组合,因此它可能会超时。您的Circle表达式有五个整型文字,因此如果Swift可以将每个整型文字视为以下任意一个,假设有12种不同的类型,那么它可以尝试的类型组合就有12种= 248,832种。Swift已经优化了这个数字,但它仍然是指数级的。
无论如何,我至少看到两种情况,您试图将Int乘以CGFloat

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

以及

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

您需要在两个位置将i转换为CGFloat

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

此外,您可能需要考虑使用Canvas来绘制reverseMaskBottomLeading,而不是使用大量修饰符的ForEach/Circle组合。

相关问题