是否可以将[AnyObject]数组转发为特定于类型的数组?

时间:2014-06-05 02:10:03

标签: arrays casting swift

我正在阅读Swift文档,查看关于类型转换的部分。

该文档讨论了如何从Foundation框架中获取类型[AnyObject]的数组(在Objective-C中将是NSArray *)。

首先,文档提供了这个示例:

for object in someObjects {
    let movie = object as Movie
    println("Movie: '\(movie.name)', dir. \(movie.director)")
}

现在,我想略微更改示例,以至于我不知道所有对象都是Movie类型的情况,所以我会这样做:

for object in someObject {
    if let movie = object as? Movie {
        println("Movie: '\(movie.name', dir. \(movie.director)")
    }
}

然后,文档提供了编写第一个循环的更好方法的示例:

for movie in someObjects as [Movie] {
   println("Movie: '\(movie.name)', dir. \(movie.director)")
}

我们将someObjects[AnyObject]转发为[Movie],这样我们就不必在循环中投降了。

这让我想到,这个阵列可以作为一个整体选择垂直吗?

if let someMovies = someObjects as? [Movie] {
    for movie in someMovies {
        println("Movie: '\(movie.name)', dir. \(movie.director)")
    }
}

这有用吗?如果是这样,从性能的角度来看,这有多糟糕?使用可选的向下转换检查10,000个元素数组中每个对象的类型需要多长时间?

据我所知,此代码段与我之前的可选向下广告代码段之间的含义不同。第一个将迭代遍历每个对象,并且只有在对象是Movie时才尝试打印,其中第二个只有在数组可以向下转换为[Movie]数组时才进入循环,在这种情况下它将打印全部或不打印,但我可以想象有些情况会更好。

2 个答案:

答案 0 :(得分:38)

您已经拥有它 - 它的工作原理与您的示例代码完全相同:

let strings = ["Hi", "Hello", "Aloha"]
let anyObjects: [AnyObject] = strings

if let downcastStrings = anyObjects as? [String] {
    println("It's a [String]")
}
// console says "It's a [String]"

不知道性能,但我不会假设它必须遍历整个数组以确定是否可以进行向下转换。


所以我很好奇,并在几个不同的[AnyObject]配置中运行了100,000个简单值的快速测试,我试图将数组向下转换为[String]而不是向下转换个别元素:

// var anyObjects: [AnyObject] = [AnyObject]()
// filled with random assortment of Int, String, Double, Bool
Running test with mixed array
downcast array execution time = 0.000522
downcast elements execution time = 0.571749

// var actuallyStrings: [AnyObject] = [AnyObject]()
// filled with String values
Running test with all strings
downcast array execution time = 1.141267
downcast elements execution time = 0.853765

将混合数组视为不可向下转换,看起来速度非常快,因为它只需要扫描直到找到非String元素。对于可以向下转换的阵列,它显然必须紧缩整个阵列,并且需要更长的时间,尽管我不确定为什么它与循环的速度不同通过数组并手动检查每个元素。

答案 1 :(得分:1)

让我们试试这个

var someObjects = [
    NSString(),
    NSUUID()
]
let uuids = someObjects as? NSUUID[]

uuids

var someOtherObjects = [
    NSUUID(),
    NSUUID()
]
let all_uuids = someOtherObjects as? NSUUID[]

all_uuids等于someOtherObjects

所以它看起来确实有效。您可以使用表达式来测试数组的所有元素是否都是预期类型,但它不会过滤数组以仅选择期望的类型。