Как создать очередь отправки в Swift 3


403

В Swift 2 мне удалось создать очередь со следующим кодом:

let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)

Но это не компилируется в Swift 3.

Каков предпочтительный способ написать это в Swift 3?



Swift 4 имеет 3 дополнительных параметра для создания последовательной очереди. Как использовать их для создания последовательной очереди? DispatchQueue.init (метка:, qos:, атрибуты:, autoreleaseFrequency:, target
:)

@ nr5 Очереди по умолчанию являются последовательными, поэтому достаточно просто использовать их DispatchQueue(label: "your-label")для последовательной очереди. Все дополнительные параметры имеют значения по умолчанию.
JBG

Ответы:


1132

Создание параллельной очереди

let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {

}  

Создать последовательную очередь

let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync { 

}

Получить основную очередь асинхронно

DispatchQueue.main.async {

}

Получить основную очередь синхронно

DispatchQueue.main.sync {

}

Чтобы получить один из фонового потока

DispatchQueue.global(qos: .background).async {

}

Xcode 8.2 beta 2:

Чтобы получить один из фонового потока

DispatchQueue.global(qos: .default).async {

}

DispatchQueue.global().async {
    // qos' default value is ´DispatchQoS.QoSClass.default`
}

Если вы хотите узнать об использовании этих очередей. Посмотрите этот ответ


4
Вы действительно можете пропустить attributes: .serialпри создании последовательной очереди: let serialQueue = DispatchQueue(label: "queuename").
Кина

15
В Xcode 8 beta 4 нет опции .serial, поэтому вы должны создать последовательную очередь, пропустив .concurrent в атрибутах.
Олег Шерман

Мне нужно получить доступ к DispatchQueue из Swift3 в objc, но возникла следующая ошибка. Невозможно инициализировать переменную типа '__strong dispatch_queue_t' (он же 'NSObject <OS_dispatch_queue> * __ strong') с значением типа 'OS_dispatch_queue * _Nonnull_ background_ display_queue_ _Nonnull_ background_ disp; = [SwiftClass Queue]; это статическая переменная DispatchQueue в swift
ideerge

DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} в Swift 3.0 я пытался с DispatchQueue.global (). Asynchronously (DispatchQueue.main) {self.mapView.add (self .mapPolyline)}, но оба показывают ту же ошибку, что и «значение типа dispathQuoue не имеет члена асинхронно»
Abirami Bala

1
из кода ОП, почему Apple фокусируется на использовании «com.swift3.imageQueue» . Я вижу, что этикетка состоит из 3 частей. Это почему? что означает каждая часть? Я не получаю форматирование
Милая

55

Компилируется под> = Swift 3 . Этот пример содержит большую часть синтаксиса, который нам нужен.

QoS - новый синтаксис качества обслуживания

weak self - чтобы нарушить удержание циклов

если личность недоступна, ничего не делай

async global utility queue- для сетевого запроса не ожидает результата, это параллельная очередь, блок (обычно) не ждет при запуске. Исключением для параллельной очереди может быть то, что, когда предел ее задачи был ранее достигнут, тогда очередь временно превращается в последовательную очередь и ожидает завершения какой-либо предыдущей задачи в этой очереди.

async main queue- для прикосновения к пользовательскому интерфейсу блок не ждет результата, а ждет своего слота в начале. Основная очередь является последовательной очередью.

Конечно, вам нужно добавить некоторые проверки ошибок к этому ...

DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in

    guard let strongSelf = self else { return }

    strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in

        if error != nil {
            print("error:\(error)")
        } else {
            DispatchQueue.main.async { () -> Void in
                activityIndicator.removeFromSuperview()
                strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
            }
        }
    }
}

6
При кодировании в Swift 3,
привыкните к сжатию

Спасибо за пример слабости!
imike

1
Это лучше , guardчто selfне nilна вершине, так что ни один из кодов не выполняется , если это nil, например, guard strongSelf = self else { return }.
Скотт Гарднер

@ t1 Не могли бы вы сказать мне, где я могу найти документацию для GCD, написанную с кодом в Swift 3? Я только нашел один написанный в Objective C . Кто-то здесь указывал мне на видео из WWDC, но я хочу прочитать официальную документацию с примерами в Swift 3, и я не могу ее найти.
bibscy

1
Не использовать .global(qos: .background)для ввода-вывода (сетевой запрос). Используйте .global(qos: .default)или .global(qos: .utility)вместо.
Педро Пауло Аморим

28

Скомпилировано в XCode 8, Swift 3 https://github.com/rpthomas/Jedisware

 @IBAction func tap(_ sender: AnyObject) {

    let thisEmail = "emailaddress.com"
    let thisPassword = "myPassword" 

    DispatchQueue.global(qos: .background).async {

        // Validate user input

        let result = self.validate(thisEmail, password: thisPassword)

        // Go back to the main thread to update the UI
        DispatchQueue.main.async {
            if !result
            {
                self.displayFailureAlert()
            }

        }
    }

}

12

Поскольку на вопрос ОП уже был дан ответ, я просто хочу добавить некоторые соображения по поводу скорости:

Очень важно, какой приоритетный класс вы назначаете асинхронной функции в DispatchQueue.global .

Я не рекомендую запускать задачи с приоритетом потока .background, особенно на iPhone X, где кажется, что задача распределена по ядрам с низким энергопотреблением.

Вот некоторые реальные данные из вычислительно интенсивной функции, которая читает из файла XML (с буферизацией) и выполняет интерполяцию данных:

Имя устройства / .background / .utility / .default / .userInitiated / .userInteractive

  1. iPhone X: 18,7 с / 6,3 с / 1,8 с / 1,8 с / 1,8 с
  2. iPhone 7: 4,6 с / 3,1 с / 3,0 с / 2,8 с / 2,6 с
  3. iPhone 5s: 7,3 с / 6,1 с / 4,0 с / 4,0 с / 3,8 с

Обратите внимание, что набор данных не одинаков для всех устройств. Это самый большой на iPhone X и самый маленький на iPhone 5s.


1
Отличная информация Помог мне
Моргз

1
@Myk Если пользователь инициировал и / или ожидает результатов, вы должны использовать .userInitiated или .userInteractive, чтобы любая другая операция была возвращена. В большинстве других случаев .default будет хорошим выбором.
Космин

6

Я сделал это, и это особенно важно, если вы хотите обновить свой пользовательский интерфейс, чтобы отображать новые данные без уведомления пользователя, как в UITableView или UIPickerView.

    DispatchQueue.main.async
 {
   /*Write your thread code here*/
 }

3
 DispatchQueue.main.async {
          self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
    }


OperationQueue.main.addOperation {
    self.lblGenre.text = self.movGenre
}

// используем Очередь операций, если вам нужно заполнить объекты (метки, изображение, текстовое представление) на вашем контроллере вида


2
   let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version

   let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version

Я переработал ваш код в Xcode 8, Swift 3, и изменения помечены в отличие от вашей версии Swift 2.


Это выглядит чище, чем я написал. Спасибо.
gosborne3

2

Свифт 3

Вы хотите вызвать некоторое замыкание в быстром коде, затем вы хотите изменить раскадровку, если вы измените любой тип, принадлежащий просмотру, ваше приложение потерпит крах

но вы хотите использовать метод отправки ваше приложение не будет падать

асинхронный метод

DispatchQueue.main.async 
{
 //Write code here                                   

}

метод синхронизации

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Я хочу использовать асинхронный метод во время вызова службы, мой код - DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") as! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animated: false)}
Amul4608

1
Никогда не используйтеDispatchQueue.main.sync
trickster77777

Синхронизация вызовов в основной очереди, безусловно, вызовет проблемы.
Воин тофу

2
DispatchQueue.main.async(execute: {

// write code

})

Серийная очередь:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Параллельная очередь:

 let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)

concurrent.sync {

 //Code Here
}

Это не создает очередь отправки, а просто помещает вас в основную очередь через один тик в цикле выполнения.
сборка завершена



1

Обновление для Swift 5

Serial Queue

let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
    // code to execute
}

Параллельная очередь

let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)

concurrentQueue.async {
// code to execute
}

Из документации Apple :

параметры

метка

Метка строки, прикрепляемая к очереди, чтобы однозначно идентифицировать ее в инструментах отладки, таких как «Инструменты», «Образцы», «Стеки» и отчеты о сбоях. Поскольку приложения, библиотеки и платформы могут создавать свои собственные очереди отправки, рекомендуется стиль именования обратного DNS (com.example.myqueue). Этот параметр является необязательным и может иметь значение NULL.

QoS

Уровень качества обслуживания для связи с очередью. Это значение определяет приоритет, при котором система планирует задачи для выполнения. Список возможных значений см. В разделе DispatchQoS.QoSClass.

атрибуты

Атрибуты, связанные с очередью. Включите параллельный атрибут для создания очереди отправки, которая выполняет задачи одновременно. Если этот атрибут не указан, очередь отправки выполняет задачи последовательно.

autoreleaseFrequency

Частота автоматического высвобождения объектов, созданных блоками, запланированными для очереди. Список возможных значений см . В разделе DispatchQueue.AutoreleaseFrequency .

цель

Целевая очередь для выполнения блоков. Укажите DISPATCH_TARGET_QUEUE_DEFAULT, если вы хотите, чтобы система предоставила очередь, подходящую для текущего объекта.


-3

теперь это просто:

let serialQueue = DispatchQueue(label: "my serial queue")

по умолчанию используется последовательный, чтобы получить параллелизм, используйте аргумент необязательных атрибутов .concurrent


Вам лучше обновить свой ответ, добавив seiralQueue.async {}. @tylemol
DawnSong

-3
DispatchQueue.main.async(execute: {
   // code
})

Спасибо за этот фрагмент кода, который может оказать некоторую немедленную помощь. Правильное объяснение значительно повысило бы его образовательную ценность, показав, почему это хорошее решение проблемы, и сделало бы его более полезным для будущих читателей с похожими, но не идентичными вопросами. Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются.
Тоби Спейт

-4

Вы можете создать очередь отправки, используя этот код в Swift 3.0

DispatchQueue.main.async
 {
   /*Write your code here*/
 }

   /* or */

let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)                   
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
  /*Write your code here*/
}

1
Извините, это не создание очереди отправки, а доступ к основной очереди после одного шага через цикл выполнения.
сборка завершена
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.