Как отправить dispatch_sync, dispatch_async, dispatch_after и т. Д. В Swift 3, Swift 4 и дальше?

У меня есть много кода в проектах 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, я получаю всевозможные ошибки. Некоторые из них предлагают исправить мой код, но не все исправления производят рабочий код. Что мне делать с этим?

С самого начала Swift предоставил некоторые возможности для создания ObjC и C более Swifty, добавляя больше с каждой версией. Теперь, в Swift 3, новая функция «import as member» позволяет фреймворкам с определенными стилями C API, где у вас есть тип данных, который работает как class, и множество глобальных функций для работы с ним – более похожи на Swift-native API. Импорт типов данных как classов Swift, их связанных глобальных функций, импортируемых как методы и свойства этих classов, и некоторые связанные с ними вещи, такие как наборы констант, могут стать подтипами там, где это необходимо.

В Xcode 8 / Swift 3 beta Apple применила эту функцию (наряду с несколькими другими), чтобы сделать Framework 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-интерфейса Dispatch, открыв его интерфейс в Xcode 8 – воспользуйтесь Open Quickly, чтобы найти модуль Dispatch, или поместите символ (например DispatchQueue ) в ваш проект Swift / игровое поле и нажмите его, а затем бросьте вокруг модуля оттуда. (API Swift Dispatch API можно найти на новом веб-сайте API Reference и в приложении Xcode doc, но похоже, что содержимое документа из версии C еще не перешло в него.)

Дополнительную информацию см. В Руководстве по миграции .

В Xcode 8 бета-версия 4 не работает …

Использование:

 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { print("Are we there yet?") } 

для асинхронных двух способов:

 DispatchQueue.main.async { print("Async1") } DispatchQueue.main.async( execute: { print("Async2") }) 

Это хороший пример для Swift 4 о async :

 DispatchQueue.global(qos: .background).async { // Background Thread DispatchQueue.main.async { // Run UI Updates or call completion block } } 

в Xcode 8:

 DispatchQueue.global(qos: .userInitiated).async { } 

Swift 4

Основная и фоновая очереди

 let main = DispatchQueue.main let background = DispatchQueue.global() let helper = DispatchQueue(label: "another_thread") 

Работа с асинхронными и синхронизирующими streamами!

  background.async { //async tasks here } background.sync { //sync tasks here } 

Асинхронные streamи будут работать вместе с основным streamом.

Потоки синхронизации будут блокировать основной stream во время выполнения.

Давайте будем гением компьютера.