The subview
property of UIView
is an array of AnyObject
. The runtime happens because you are performing a forced downcast from [AnyObject]
to [UIButton]
.
From a compiler perspective, the down cast is legit:
let x: [UIButton] = [AnyObject]() as [UIButton]
because AnyObject
can be any class, and UIButton
is a class.
In your case you are making the assumption that all objects contained in subviews
are instances of UIButton
, which can be possible (if you explicitly add UIButton
s only to the view), but if the view has other UI elements (labels, other views, etc.) then the downcast will fail at runtime.
If for example the view contains another view, the above downcast is equivalent to doing this:
var view = UIView()
var button = view as UIButton
which fails because a UIView
is not a UIButton
(although thanks to polymorphism the opposite is true, being UIButton
inherited from UIView
).
If you want your code to print the tag for all UIButton
s, ignoring all other UI elements, then @rahul_send89's answer is the correct one: it loops through all elements of the subview
property, and it prints the tag only if the current element is a UIButton
.
@SteveRosenberg's answer instead print the tag for all elements, regardless of their actual type.
Depending on what you want to do with your buttons (I presume the code posted in your question is just placeholder to explain the problem), there's an alternate way: filtering all buttons from the subviews
property and storing into an array:
var buttons = mainView.subviews.filter { $0 is UIButton } as [UIButton]
and do whatever you need with this array of UIButton
, such as printing their tag.
for button in buttons {
println(button.tag)
}