当我使用case let
投射视图时,Swift可以正确识别循环内circle
到PinCircleView
的类型
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
不会强制转换,而只会检查类型,但这使我想到另一个问题,如果类型匹配,为什么我不能“完全”使用它?
答案 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)
元组的序列。因此,在这种情况下,circle
是UIView
。
然后,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
。