Подтвердить что ты не робот

Может ли [AnyObject] массив быть необязательно опущен в массив типа?

Я читаю документацию Swift, рассматривая раздел о литье типов.

В документации говорится о получении массива типа [AnyObject] из материала фреймворка Foundation (что было бы NSArray * в Objective-C).

Во-первых, в документации приведен пример:

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)")
    }
}

Это работает? И если да, насколько это плохо с точки зрения производительности? Сколько времени потребуется, чтобы проверить тип каждого объекта в массиве из 10000 элементов, используя необязательный downcast?

Я понимаю, что последствия между этим фрагментом и моим предыдущим необязательным снижением фрагмента различны. Первый будет перебирать каждый объект и только попытаться распечатать, если объект является Movie, где второй будет вводить только цикл, если массив может быть опущен до массива [Movie], и в этом случае он либо распечатает все или нет, но я могу представить себе, что есть ситуации, когда это было бы предпочтительнее.

4b9b3361

Ответ 1

У вас это есть - он работает точно так же, как ваш пример кода:

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

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

Не знаю о производительности, но я бы не стал предполагать, что ему придется перебирать весь массив, чтобы определить, возможно ли понижение.


Итак, мне стало любопытно, и я провел быстрый тест со 100 000 простых значений в нескольких разных конфигурациях [AnyObject], где я пытаюсь свести массив к [String] по сравнению с downcasting отдельными элементами:

// 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. Для массива, который он может сбрасывать, он явно должен хрустить по всему массиву и занимает гораздо больше времени, хотя я не уверен, почему это не такая же скорость, как цикл через массив и ручная проверка каждого элемента.

Ответ 2

Попробуйте это

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

uuids - nil

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

all_uuids равно someOtherObjects

Итак, похоже, что он работает. Вы можете использовать выражение для проверки того, соответствуют ли все элементы массива ожидаемого типа, но он не будет фильтровать массив для выбора только ожидаемого типа.