Как отменить выполнение задачи (NSOperation) в Swift?

«Как отменить выполнение задачи (NSOperation) в Swift?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Задачу можно отменить, вызвав метод cancel() у экземпляра NSOperation или Operation. Однако отмена является кооперативной — операция не прекращается мгновенно, а лишь устанавливает свойство isCancelled в true. Код внутри операции должен периодически проверять это свойство и корректно завершать свою работу.

Правильная реализация отмены в кастомной операции:

class MyLongOperation: Operation {
    override func main() {
        // 1. Проверить отмену перед началом работы
        guard !isCancelled else { return }

        // 2. Выполнять длительную работу с периодическими проверками
        for i in 1...1000 {
            if isCancelled { // 3. Проверка в цикле
                // Очистка ресурсов при необходимости
                return
            }
            // ... выполнение шага работы ...
            print("Step (i)")
        }
    }
}

// Использование
let operationQueue = OperationQueue()
let operation = MyLongOperation()
operationQueue.addOperation(operation)

// Отмена операции через 2 секунды
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    operation.cancel() // Устанавливает isCancelled = true
}

Важные моменты:

  • После вызова cancel() операция остается в очереди до момента, когда ее main() метод завершится.
  • Свойства isFinished и isExecuting меняются системой только после реального завершения main().
  • Для отмены всех операций в очереди используйте operationQueue.cancelAllOperations().
  • Отмененные зависимости (addDependency) не препятствуют запуску зависящей операции, если она готова к выполнению.