Как мне отправить синхронизацию, отправить асинхронность, отправить после и т. д. В 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")
}
или любые другие виды использования API Grand Central Dispatch...
теперь, когда я открыл свой проект в Xcode 8 (бета) для Swift 3, я получаю все виды ошибок. Некоторые из них предлагают исправить мой код, но не все исправления производят рабочий код. Что мне с этим делать?
6 ответов:
С самого начала Swift предоставил некоторые возможности для создания ObjC и C более Swifty, добавляя больше с каждой версией. Теперь, в Swift 3, новый "импортировать как член" функция позволяет фреймворкам с определенными стилями C API - где у вас есть тип данных, который работает как класс, и куча глобальных функций для работы с ним-действуют больше как Swift-native API. Типы данных импортируются как классы Swift, связанные с ними глобальные функции импортируются как методы и свойства на этих классах и некоторые связанные с ними вещи, такие как наборы констант, могут стать подтипами, где это уместно.
в бета-версии Xcode 8 / Swift 3 Apple применила эту функцию (наряду с несколькими другими), чтобы сделать структуру отправки намного более быстрой. (И Ядра Графика тоже.) Если вы следили за стремительными усилиями с открытым исходным кодом,это не новость, но теперь это первый раз, когда это часть Xcode.
ваш первый шаг на перемещение любого проект для Swift 3 должно быть, чтобы открыть его в Xcode 8 и выбрать Edit > Convert > To Current Swift Syntax... в меню. Это будет применяться (с вашим обзором и утверждением) все изменения сразу, необходимые для всех переименованных 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 -- use Open Быстро найти модуль отправки, или поставить символ (например
DispatchQueue
) в вашем Swift project/playground и command-click it, а затем brouse вокруг модуля оттуда. (Вы можете найти Swift отправка API на новом веб-сайте Apple spiffy New 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 } }
Swift 4
основные и фоновые очереди
let main = DispatchQueue.main let background = DispatchQueue.global() let helper = DispatchQueue(label: "another_thread")
работа с async и синхронизация нити!
background.async { //async tasks here } background.sync { //sync tasks here }
асинхронные потоки будут работать вместе с основным потоком.
синхронизация потоков будет блокировать основной поток во время выполнения.
Swift 4.1. Мы используем очереди во многих местах в коде. Итак, я создал класс Threads со всеми очередями. Если вы не хотите использовать класс темы, вы можете скопировать нужный код очереди из методов класса.
class Threads { static let concurrentQueue = DispatchQueue(label: "AppNameConcurrentQueue", attributes: .concurrent) static let serialQueue = DispatchQueue(label: "AppNameSerialQueue") // Main Queue class func performTaskInMainQueue(task: @escaping ()->()) { DispatchQueue.main.async { task() } } // Background Queue class func performTaskInBackground(task:@escaping () throws -> ()) { DispatchQueue.global(qos: .background).async { do { try task() } catch let error as NSError { print("error in background thread:\(error.localizedDescription)") } } } // Concurrent Queue class func perfromTaskInConcurrentQueue(task:@escaping () throws -> ()) { concurrentQueue.async { do { try task() } catch let error as NSError { print("error in Concurrent Queue:\(error.localizedDescription)") } } } // Serial Queue class func perfromTaskInSerialQueue(task:@escaping () throws -> ()) { serialQueue.async { do { try task() } catch let error as NSError { print("error in Serial Queue:\(error.localizedDescription)") } } } // Perform task afterDelay class func performTaskAfterDealy(_ timeInteval: TimeInterval, _ task:@escaping () -> ()) { DispatchQueue.main.asyncAfter(deadline: (.now() + timeInteval)) { task() } } }
пример, показывающий использование основной очереди.
override func viewDidLoad() { super.viewDidLoad() Threads.performTaskInMainQueue { self.tblViewSignUP.reloadData() } }