Как новый язык программирования 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!")
}
}