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

См. Страницу веб-сайта Apple на Swift: https://developer.apple.com/swift/

Есть ли в Swift блоки, как в target-c? Как они созданы и названы?

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

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

3 ответа

Решение

Свифт-эквивалент блока (Objective-)C называется замыканием. О них есть целая глава в книге "Язык программирования Swift".

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

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

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

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

Выдержка из: Apple Inc. "Язык программирования Swift". IBooks. https://itun.es/us/jEUH0.l

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

Во-первых, сигнатура функции может быть выведена, поэтому вам не нужно ее переписывать.

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!")
    }
}
Другие вопросы по тегам