Как 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!")
}
}