В чем плюсы и минусы NSOperation по сравнению с GCD
Что проверяют
Понимаете ли вы, что Operation это надстройка над GCD, и можете ли выбрать инструмент под задачу, а не пересказать список плюсов. Следом часто спрашивают, как написать асинхронную операцию и что из этого сейчас заменяет Swift Concurrency.
Как отвечать
В Swift это Operation и OperationQueue. Что даёт очередь операций поверх GCD:
- зависимости:
addDependency(_:)строит граф, операция стартует, когда завершились все, от кого она зависит; - ограничение параллельности:
maxConcurrentOperationCount, например не больше трёх загрузок одновременно; - состояния и KVO:
isReady,isExecuting,isFinished,isCancelled, на них можно подписаться; - отмена:
cancel()у операции илиcancelAllOperations()у очереди. Отмена кооперативная: уже запущенная операция должна сама проверятьisCancelled.
GCD проще и легче: DispatchQueue.async, DispatchGroup с notify для ожидания пачки задач, флаг .barrier для схемы «много читателей, один писатель», DispatchSemaphore. Отменять в GCD тоже можно: DispatchWorkItem.cancel() не даст стартовать задаче, которая ещё в очереди, но запущенную не прервёт.
Минус операций в том, что асинхронную операцию пишут вручную: переопределить isAsynchronous и start(), потокобезопасно менять isExecuting и isFinished и отправлять KVO-уведомления. Ошибка здесь даёт операцию, которая не завершится никогда.
В новом коде обе технологии всё чаще заменяют async/await, TaskGroup и акторы: там структурная отмена, а в Swift 6 компилятор проверяет гонки данных. Operation и GCD остаются в унаследованном коде и на стыке со старыми API.
Где спотыкаются
Считают, что cancel() останавливает работу. Он только ставит флаг, и без проверок isCancelled операция доработает до конца.
Запускают асинхронный запрос внутри main() обычной операции. Операция завершается сразу, до ответа сети, и зависимые операции стартуют раньше времени.
Говорят, что в GCD нет ни отмены, ни зависимостей. Отмена есть через DispatchWorkItem, а порядок решается последовательной очередью или DispatchGroup, просто без готового графа.