У меня есть много кода в проектах Swift 2.x(или даже 1.x), которые выглядят следующим образом:
// Move to a background thread to do some long running work
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let image = self.loadOrGenerateAnImage()
// Bounce back to the main thread to update the UI
dispatch_async(dispatch_get_main_queue()) {
self.imageView.image = image
}
}
Или что-то вроде этого для задержки выполнения:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
print("test")
}
Или любое из других видов использования Grand Central Dispatch API...
Теперь, когда я открыл свой проект в Xcode 8 (бета) для Swift 3, я получаю всевозможные ошибки. Некоторые из них предлагают исправить мой код, но не все исправления производят рабочий код. Halp! Что мне делать с этим?
С самого начала Swift предоставил некоторые возможности для создания ObjC и C более Swifty, добавляя больше с каждой версией. Теперь в Swift 3 новая функция import as member позволяет создавать фреймворки с определенными стилями C API, где у вас есть тип данных, который работает как класс, и куча глобальных функций для работы с ним - больше походит на Swift-native API. Импорт типов данных как классов Swift, их связанных глобальных функций, импортируемых как методы и свойства этих классов, и некоторые связанные с ними вещи, такие как наборы констант, могут при необходимости становиться подтипами.
В Xcode 8/Swift 3 beta Apple применила эту функцию (наряду с несколькими другими), чтобы сделать платформу Dispatch намного более Swifty. (И Core Graphics). Если вы следовали за усилиями с открытым исходным кодом Swift, это не новость, но теперь это первый раз, когда он является частью Xcode.
Первым шагом при перемещении любого проекта в Swift 3 должно быть открытие его в Xcode 8 и в меню выберите "Редактирование" > "Преобразовать" > "Текущий синтаксис Swift".... Это применит (с вашим обзором и одобрением) все изменения, необходимые для всех переименованных API и других изменений. (Часто на строку кода влияет более чем одно из этих изменений сразу, поэтому реагирование на исправление ошибок - по отдельности может не справиться со всем правильным.)
Результат состоит в том, что общий шаблон для отскока работы на фоне и обратно теперь выглядит следующим образом:
// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
let image = self.loadOrGenerateAnImage()
// Bounce back to the main thread to update the UI
DispatchQueue.main.async {
self.imageView.image = image
}
}
Обратите внимание, что мы используем .userInitiated
вместо одной из старых констант DISPATCH_QUEUE_PRIORITY
. Спецификаторы качества обслуживания (QoS) были представлены в OS X 10.10/iOS 8.0, предоставляя более четкий способ для системы расставить приоритеты в работе и отказаться от старых спецификаторов приоритета. Подробнее см. Apple документы о фоновой работе и энергоэффективности.
Кстати, если вы сохраняете собственные очереди для организации работы, способ получить ее теперь выглядит следующим образом (обратите внимание, что DispatchQueueAttributes
- это OptionSet
, поэтому вы используете литералы в стиле коллекции, чтобы комбинировать параметры ):
class Foo {
let queue = DispatchQueue(label: "com.example.my-serial-queue",
attributes: [.serial, .qosUtility])
func doStuff() {
queue.async {
print("Hello World")
}
}
}
С помощью dispatch_after
выполните работу позже? Это также метод в очередях, и он принимает DispatchTime
, который имеет операторы для различных числовых типов, поэтому вы можете просто добавить целые или дробные секунды:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
print("Are we there yet?")
}
Вы можете найти свой путь вокруг нового API-интерфейса отправки, открыв его интерфейс в Xcode 8 - используйте Open Quickly, чтобы найти модуль Dispatch, или поместите символ (например, DispatchQueue
) в ваш проект Swift/playground и командную строку, щелкните по нему, а затем разглядывайте модуль. (Вы можете найти API Swift Dispatch в новом веб-сайте API Reference и в приложении Xcode doc, но это похоже на содержимое документа из версии C еще не переместился в нее.)
Подробнее см. в Руководство по миграции.
в xcode 8 beta 4 не работает. Использование:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
print("Are we there yet?")
}
для асинхронизации двумя способами:
DispatchQueue.main.async {
print("Async1")
}
DispatchQueue.main.async( execute: {
print("Async2")
})
в xcode8 используйте:
DispatchQueue.global(qos: .userInitiated).async { }
Это хороший пример для Swift 3
около async
:
DispatchQueue.global(qos: .background).async {
// Background Thread
DispatchQueue.main.async {
// Run UI Updates
}
}
Основные и фоновые очереди
let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread")
Работа с потоками асинхронной и синхронизации!
background.async { //async tasks here }
background.sync { //sync tasks here }
Асинхронные потоки будут работать вместе с основным потоком.
Синхронизирующие потоки будут блокировать основной поток при выполнении.