enumerateObjectsUsingBlock - приведение параметров в Swift

Я хочу сослаться на перечисленные объекты с их конкретным типом, а не просто общий AnyObject!, но не могу найти никакой информации об этом в документации.

Подпись enumerateObjectsUsingBlock в Свифте есть:

func enumerateObjectsUsingBlock(_ block: ((AnyObject!,
                                         Int,
                                         UnsafePointer<ObjCBool>) -> Void)!)

и в Задаче C:

- (void)enumerateObjectsUsingBlock:(void (^)(id obj,
                                     NSUInteger idx,
                                     BOOL *stop))block

Если я хочу обрабатывать объекты, которые повторяются, как определенный тип, в Objective CI просто настройте подпись на лету, например:

[array enumerateObjectsUsingBlock:^(NSString *s, NSUInteger idx, BOOL *stop){
    // ...some function of s as NSString, not just id... 
}];

Как мне получить это поведение в Swift?

2 ответа

Решение

В Swift вы не можете "подправить" подпись блока / замыкания, как в Objective-C, вы должны привести в явном виде. Либо с дополнительным приведением:

array.enumerateObjectsUsingBlock({ object, index, stop in
    if let str = object as? String {
        println(str)
    }
})

или с принудительным приведением, если вы уверены, что все объекты являются строками:

array.enumerateObjectsUsingBlock({ object, index, stop in
    let str = object as String // `as!` in Swift 1.2
    println(str)
})

поскольку NSArray мосты к Array Вы можете без проблем использовать Array перечисление:

for str in array as [String] {
    println(str)
}

или, если вам нужны элементы вместе с их индексом:

for (index, str) in enumerate(array as [String]) {
    println("\(index): \(str)")
}

Обновление для Swift 3.0

С enumerateObjects(using:):

array.enumerateObjects(using: { (object, index, stop) in
    if let str = object as? String {
        print("\(index): \(str)")
    }
})

Перечислите как массив Swift:

if let a = array as? [String] {
    for str in a {
        print(str)
    }
}

Перечислите элементы и индексы в виде массива Swift:

if let a = array as? [String] {
    for (index, str) in a.enumerated() {
        print("\(index): \(str)")
    }
}

Я рекомендую использовать оператор swift for/each, который автоматически предоставляет каждый элемент в качестве переменной типа, содержащегося в массиве swift:

let array: [String] = ["1", "2", "3"]

for element in array {
    println(element) // element is of String type
}

С NSArray Вы можете использовать то же утверждение, но с явным приведением:

let nsarray: NSArray = ["1", "2", "3"]

for element in nsarray {
    let value = element as String // note: use `as!` in swift 1.2
    println(value)
}

Если вы все еще используете enumerateObjectsUsingBlock:

nsarray.enumerateObjectsUsingBlock { (element, index, stop) in
    let stringElement = element as String
    println(stringElement)
}
Другие вопросы по тегам