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

时间:2019-09-14 22:22:22

标签: swift casting typechecking

当我使用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不会强制转换,而只会检查类型,但这使我想到另一个问题,如果类型匹配,为什么我不能“完全”使用它?

1 个答案:

答案 0 :(得分:3)

快速类型是在编译时间建立的。

在第一种情况下,case let仅在类型为(index, circle)时才将值分配给(Int, PinCircleView)。因此,在编译时,Swift知道circle的类型为PinCircleView。您可以通过选项-单击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返回[UIView],而.enumerated()将其转换为(Int, UIView)元组的序列。因此,在这种情况下,circleUIView

然后,where circle is PinCircleView检查circle是否包含PinCircleView的{​​{1}}子类,但是它不会改变UIView被键入为{ {1}}。同样,使用 option 并单击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,但是Swift没有。您可以使用circle在循环内向下转换它,并知道它总是可以正常工作而不会崩溃,因为您使用PinCircleView检查了它。

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