OperationQueue.main vs DispatchQueue.main

Когда вам нужно что-то выполнить в основном потоке в блоке завершения сетевой задачи или операции, какой из этих способов ее получить будет наиболее подходящим и почему?:

  • OperationQueue.main.addOperation
  • DispatchQueue.main.async

Ответ 1

Подробнее о различиях между двумя типами очереди см. в комментарии Lion.

Оба подхода будут работать. Однако NSOperation в основном требуется, когда требуется более продвинутое планирование (включая зависимости, отмена и т.д.). Итак, в этом случае простая

DispatchQueue.main.async { /* do work */ }

будет просто отлично. Это будет эквивалентно

dispatch_async(dispatch_get_main_queue(), ^{ /* do work */ });

в Objective-C, что также я хотел бы сделать это на этом языке.

Ответ 2

Когда использовать NSOperation

API NSOperation отлично подходит для инкапсуляции четко определенных блоков функциональности. Например, вы можете использовать подкласс NSOperation для инкапсуляции последовательности входа в приложение.

Управление зависимостями - обледенение на торте. Операция может иметь зависимости от других операций, и это очень мощная функция, которой не хватает в Grand Central Dispatch. Если вам нужно выполнить несколько задач в определенном порядке, тогда операции являются хорошим решением.

Вы можете перейти за борт с операциями, если вы создаете десятки операций за короткий промежуток времени. Это может привести к проблемам с производительностью из-за накладных расходов, присущих NSOperation API.

Когда использовать Grand Central Dispatch

Grand Central Dispatch является идеальным, если вам просто нужно отправить блок кода в последовательную или параллельную очередь.

Если вы не хотите преодолевать трудности создания NSOperation subclass для тривиальной задачи, то Grand Central Dispatch - отличная альтернатива. Еще одно преимущество Grand Central Dispatch заключается в том, что вы можете сохранить связанный код вместе. Взгляните на следующий пример.

let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
// Process Response
...

dispatch_async(dispatch_get_main_queue(), { () -> Void in
    // Update User Interface
    ...
})
})

В обработчике завершения задачи данных мы обрабатываем ответ и обновляем пользовательский интерфейс, отправляя замыкание (или блок) в основную очередь. Это необходимо, потому что мы не знаем, в какой поток выполняется обработчик завершения, и это скорее всего фоновый поток.

Цитата из этот источник

Ответ 3

DispatchQueue управляет выполнением рабочих элементов. Каждый рабочий элемент, отправленный в очередь, обрабатывается в пуле потоков, управляемых системой.

Ссылка: Apple Doc

Класс NSOperationQueue регулирует выполнение набора объектов Operation. После добавления в очередь в этой очереди остается операция до тех пор, пока она не будет явно отменена или не завершит выполнение своей задачи. Операции в очереди (но еще не выполняющиеся) сами организованы в соответствии с уровнями приоритета и зависимостями между операционными объектами и выполняются соответствующим образом. Приложение может создавать несколько очередей операций и отправлять операции любому из них.

Ссылка: Apple Doc

Итак, вы должны предпочесть DispatchQueue.main.async, когда хотите выполнить что-то в основном потоке из блока завершения любого сетевого вызова. Особенно, когда это связано с UI Updates! И если ваша задача сложная, я имею в виду, если вам требуется дополнительная операция при запуске задачи, вы можете пойти с OperationQueue.main.addOperation иначе DispatchQueue.main.async даст более оптимальную производительность сравнительно!