在for-in循环中键入cast

Arb*_*tur 111 for-loop for-in-loop swift

我有这个for-in循环:

for button in view.subviews {
}
Run Code Online (Sandbox Code Playgroud)

现在我想将按钮转换为自定义类,以便我可以使用它的属性.

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

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

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

但这也不起作用.

vac*_*ama 157

对于Swift 2及更高版本:

Swift 2 为for循环添加了case模式,这使得在for循环中输入类型变得更加容易和安全:

for case let button as AClass in view.subviews {
    // do something with button
}
Run Code Online (Sandbox Code Playgroud)

为什么这比你在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)
}
Run Code Online (Sandbox Code Playgroud)

输出:

Hello
World!
Run Code Online (Sandbox Code Playgroud)

对于Swift 1.2:

在这种情况下,你是铸造view.subviews,而不是button,所以你需要将其向下到你想要的类型的数组:

for button in view.subviews as! [AClass] {
    // do something with button
}
Run Code Online (Sandbox Code Playgroud)

注意:如果基础数组类型不是[AClass],则会崩溃.这就是!on 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
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Swift 1.1及更早版本:

for button in view.subviews as [AClass] {
    // do something with button
}
Run Code Online (Sandbox Code Playgroud)

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


obe*_*ber 122

此选项更安全:

for case let button as AClass in view.subviews {
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是IMO的正确答案. (4认同)

ede*_*y05 5

您也可以使用where子句

for button in view.subviews where button is UIButton {
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • where子句是一个布尔型保护,但是不会在循环体内强制转换“ button”的类型,这是其他解决方案的目标。因此,这只会在UIButton的view.subviews元素上运行循环体,但对例如在button上调用特定于AClass的方法没有帮助。 (10认同)

use*_*800 5

提供的答案是正确的,我只是想将其添加为补充。

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

for button in view.subviews as! [AClass] {
    // do something with button
}
Run Code Online (Sandbox Code Playgroud)

但不是使用 if 子句,

if let subviews = view.subviews as? [AClass] {
    // If we get here, then subviews is of type [AClass]
    ...
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用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
    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果数组的某些元素(但不是全部)可能是 类型,这似乎更方便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 {
    // ...
}
Run Code Online (Sandbox Code Playgroud)