Reputation: 931
When I'm casting views with case let
Swift properly recognizes the type of circle
to PinCircleView
inside the loop
for case let (index, circle) as (Int, PinCircleView) in pinCirclesStackView.arrangedSubviews.enumerated() {
print(index, circle) // <- circle is PinCircleView and print's as expected
}
But if I'm type checking with is
Swift still only allows me to access circle
as it would be UIView
for (index, circle) in pinCirclesStackView.arrangedSubviews.enumerated() where circle is PinCircleView {
print(index, circle) // <- circle is UIView but print's PinCircleView
}
If I'm understanding correctly is
does not cast but only checks the type, but this leads me to another question if the type is matched why can't I "fully" use it?
Upvotes: 0
Views: 140
Reputation: 154513
Swift types are established at compile time.
In the first case, the case let
only assigns values to (index, circle)
if the types are (Int, PinCircleView)
. So at compile time, Swift knows circle
is of type PinCircleView
. You can verify this by option-clicking on circle
.
for case let (index, circle) as (Int, PinCircleView) in pinCirclesStackView.arrangedSubviews.enumerated() {
print(index, circle) // <- circle is PinCircleView and print's as expected
}
In the second case, (index, circle)
gets assigned every value from arrangedSubviews.enumerated()
. In that case, arrangedSubviews
returns [UIView]
and .enumerated()
turns that into a sequence of (Int, UIView)
tuples. So in this case, circle
is a UIView
.
The where circle is PinCircleView
then checks if circle
contains the PinCircleView
subclass of UIView
, but it doesn't change the fact that circle
is typed as UIView
. Again, use option-click on circle
to verify that its type is UIView
.
for (index, circle) in pinCirclesStackView.arrangedSubviews.enumerated() where circle is PinCircleView {
print(index, circle) // <- circle is UIView but print's PinCircleView
}
Inside of the for
, you know that circle
contains a PinCircleView
, but Swift doesn't. You could downcast it inside of the loop with let pincircle = circle as! PinCircleView
and know that it would always work without crashing because you checked it using is
.
But the better form is to use the for case let
version to properly establish the type of circle
as PinCircleView
.
Upvotes: 3