Swift 无法在循环中推断条件类型

Swift can't infer conditional type in a loop

当我使用 case let 投射视图时 Swift 在循环

中正确识别 circlePinCircleView 的类型
 for case let (index, circle) as (Int, PinCircleView) in pinCirclesStackView.arrangedSubviews.enumerated() {
    print(index, circle) // <- circle is PinCircleView and print's as expected 
 }

但是,如果我使用 is 进行类型检查,Swift 仍然只允许我访问 circle,因为它会是 UIView

for (index, circle) in pinCirclesStackView.arrangedSubviews.enumerated() where circle is PinCircleView {
  print(index, circle) // <- circle is UIView but print's PinCircleView
}

如果我理解正确,is 不会强制转换,而只会检查类型,但这让我想到了另一个问题,如果类型匹配,为什么我不能 "fully" 使用它?

Swift 类型在 编译时建立

在第一种情况下,case let 仅在类型为 (Int, PinCircleView) 时才将值赋给 (index, circle)。所以在编译时,Swift 知道 circlePinCircleView 类型。您可以通过 选项 -单击 circle.

来验证这一点
for case let (index, circle) as (Int, PinCircleView) in pinCirclesStackView.arrangedSubviews.enumerated() {
    print(index, circle) // <- circle is PinCircleView and print's as expected
}

在第二种情况下,(index, circle) 被分配了 arrangedSubviews.enumerated() 的每个值。在这种情况下,arrangedSubviews returns [UIView].enumerated() 将其转换为 (Int, UIView) 元组序列。所以在这种情况下,circleUIView.

然后 where circle is PinCircleView 检查 circle 是否包含 UIViewPinCircleView 子类,但它不会改变 circle 类型的事实作为 UIView。同样,使用 选项 - 单击 circle 以验证其类型为 UIView.

for (index, circle) in pinCirclesStackView.arrangedSubviews.enumerated() where circle is PinCircleView {
    print(index, circle) // <- circle is UIView but print's PinCircleView
}

for 内部,您知道 circle 包含 PinCircleView,但 Swift 不包含。您可以使用 let pincircle = circle as! PinCircleView 在循环内向下转换它,并且知道它始终可以工作而不会崩溃,因为您使用 is.

检查了它

但更好的形式是使用 for case let 版本将 circle 的类型正确地建立为 PinCircleView