Как Apple новый язык программирования Swift обрабатывает блоки и асинхронные запросы?

C.f. Веб-страница Apple на странице Swift: https://developer.apple.com/swift/

Существуют ли блоки в Swift, как в objective-c? Как они созданы и называются?

Как выполнить асинхронный запрос в Swift?

Легко ли создавать быстрые потоки памяти, связанные с блоком? Если да, как бы вы их избежали?

Ответ 1

Скрытый эквивалент блока (Objective-) C называется замыканием. Там целая глава о них в книге Swift Programming Language.

В зависимости от контекста, в котором вы используете закрытие, вы можете объявить/использовать его с очень кратким синтаксисом. Например, метод, который принимает обработчик завершения, чья подпись (success: Bool, error: NSError) - > Void может быть вызвана следующим образом:

someMethod(otherParameters: otherValues, completionHandler:{ success, error in
    if !success { NSLog("I am a leaf on the wind: %@", error) }
})

Также существует синтаксис закрывающего закрытия, который хорошо читается в тех случаях, когда закрытие по существу обеспечивает управление потоком. И вы можете отбросить имена параметров, если хотите быть очень краткими (при некоторой цене на удобочитаемость, но это хорошо в некоторых очевидных случаях, таких как ниже). Часто оператор return тоже неявный.

myArray.sort { $0 < $1 }
let squares = myArray.map { value in
    value * 2
}    

У самой Swift ничего нет для асинхронных запросов, поэтому для этого вы используете существующий API. Вы можете использовать синтаксис трейлинг-закрытия:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // do some async stuff
    NSOperationQueue.mainQueue().addOperationWithBlock {
        // do some main thread stuff stuff
    }
}

В большинстве случаев вам не нужно беспокоиться о создании ссылочных циклов с закрытием Swift, как вы это делаете с блоками ObjC. Проще говоря, семантика захвата подобна достаточно, чтобы "просто работать" так, как вы хотите, для большинства вещей, но достаточно различной, чтобы использовать общие шаблоны для блокирования/закрытия (например, отправка в фоновый/основной поток и ссылка self свойства) не вызывают циклов.

Циклы все еще возможны, и есть решение для них. Этот ответ уже довольно давно, поэтому ознакомьтесь с Сильными ссылочными циклами для закрытий в документах для полного объяснения.

Ответ 2

Блоки в Swift называются замыканиями. Они работают так же, как и блоки (хотя они более гибкие и работают в большем количестве мест). Целевые циклы возможны с закрытием в Swift, и их можно избежать с помощью списков захвата закрытия.

"Swift предлагает элегантное решение этой проблемы, известное как список захвата закрытия. Однако, прежде чем вы узнаете, как разбить сильный ссылочный цикл с помощью списка захвата закрытия, полезно понять, как такой цикл может быть вызван"

Отрывок из: Apple Inc. "Быстрый язык программирования". интерактивные книги. https://itun.es/us/jEUH0.l

Ответ 3

Как я уже сказал в другом вопросе, у вас есть много способов передать блок, эквивалентный функции в Swift.

Я нашел три.

Чтобы понять это, я предлагаю вам испытать на детской площадке этот маленький кусок кода.

func test(function:String -> String) -> String
{
    return function("test")
}

func funcStyle(s:String) -> String
{
    return "FUNC__" + s + "__FUNC"
}
let resultFunc = test(funcStyle)

let blockStyle:(String) -> String = {s in return "BLOCK__" + s + "__BLOCK"}
let resultBlock = test(blockStyle)

let resultAnon = test({(s:String) -> String in return "ANON_" + s + "__ANON" })


println(resultFunc)
println(resultBlock)
println(resultAnon)

Обновление: для анонимной функции есть 2 специальных случая.

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

let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })

Второй специальный случай работает только в том случае, если блок является последним аргументом, он называется закрывающим закрытием

Вот пример (объединенный с выведенной сигнатурой для отображения мощности Swift)

let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }

Наконец, в качестве примера:

Используя всю эту силу, я сделаю смешение закрывающего закрытия и ввода типа (с именованием для удобочитаемости)

PFFacebookUtils.logInWithPermissions(permissions) {
    user, error in
    if (!user) {
        println("Uh oh. The user cancelled the Facebook login.")
    } else if (user.isNew) {
        println("User signed up and logged in through Facebook!")
    } else {
        println("User logged in through Facebook!")
    }
}