输入回路型铸造

我有这个 for-in 循环:

for button in view.subviews {
}

现在,我希望按钮被强制转换为一个自定义类,这样我就可以使用它的属性。

我试过这个: for button in view.subviews as AClass

但它不工作,并给我一个错误: 'AClass' does not conform to protocol 'SequenceType'

我试了这个: for button:AClass in view.subviews

但这也不管用。

40295 次浏览

对于 Swift 2及更高版本:

Swift 2将 案件模式添加到 为了循环中,这使得在 为了循环中输入 cast 更加容易和安全:

for case let button as AClass in view.subviews {
// do something with button
}

为什么这比你在 Swift 1.2和更早的版本中做的更好?因为 案件模式允许您从集合中选择特定的类型。它只匹配您正在查找的类型,因此如果数组包含混合类型,则只能对特定类型进行操作。

例如:

let array: [Any] = [1, 1.2, "Hello", true, [1, 2, 3], "World!"]
for case let str as String in array {
print(str)
}

产出:

Hello
World!

对于 Swift 1.2:

在这种情况下,您正在强制转换 view.subviews而不是 button,因此您需要将其向下转换为所需类型的数组:

for button in view.subviews as! [AClass] {
// do something with button
}

注意: 如果基础数组类型不是 [AClass],这将崩溃。这就是 as!上的 !告诉你的。如果不确定类型,可以使用条件强制转换 as?和可选绑定 if let:

if let subviews = view.subviews as? [AClass] {
// If we get here, then subviews is of type [AClass]
for button in subviews {
// do something with button
}
}

对于 Swift 1.1及更早版本:

for button in view.subviews as [AClass] {
// do something with button
}

注意: 如果子视图不都是 AClass类型的,这也会崩溃。上面列出的安全方法也适用于早期版本的 Swift。

Vacawama 提供的答案在 Swift 1.0中是正确的,而且不再适用于 Swift 2.0。

如果你尝试,你会得到一个类似的错误:

“[ AnyObject ]”不能转换为“[ AClass ]”;

在 Swift 2.0中,你需要这样写:

for button in view.subviews as! [AClass]
{
}

这种选择更为安全:

for case let button as AClass in view.subviews {
}

或快速的方式:

view.subviews
.compactMap { $0 as AClass }
.forEach { .... }

还可以使用 where子句

for button in view.subviews where button is UIButton {
...
}

所提供的答案是正确的,我只是想添加这个作为补充。

当使用强制强制转换的 for 循环时,代码将崩溃(其他代码已经提到过)。

for button in view.subviews as! [AClass] {
// do something with button
}

但是没有使用 if 子句,

if let subviews = view.subviews as? [AClass] {
// If we get here, then subviews is of type [AClass]
...
}

另一种方法是使用 while 循环:

/* If you need the index: */
var iterator = view.subviews.enumerated().makeIterator()
while let (index, subview) = iterator.next() as? (Int, AClass) {
// Use the subview
// ...
}


/* If you don't need the index: */
var iterator = view.subviews.enumerated().makeIterator()
while let subview = iterator.next().element as? AClass {
// Use the subview
// ...
}

如果数组的某些元素(但不是全部)可能是 AClass类型,那么这似乎更方便。

虽然现在(在 Swift 5中) ,我会使用 for-case 循环:

for case let (index, subview as AClass) in view.subviews.enumerated() {
// ...
}


for case let subview as AClass in view.subviews {
// ...
}

您可以执行铸造,同时是安全的:

for button in view.subviews.compactMap({ $0 as? AClass }) {


}

如果你想在你的循环中有一个 索引:

for case let (index, button as AClass) in view.subviews.enumerated() {
}