Как правильно отменить выполнение Operation в Swift?

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

Ответ

Отмена Operation — кооперативный процесс. Вызов cancel() лишь устанавливает флаг isCancelled, но не останавливает выполнение немедленно. Сама операция должна регулярно проверять этот флаг и завершаться.

1. Базовая отмена в кастомной Operation

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

        // 2. Выполнить часть работы...

        // 3. Проверять отмену в длительных циклах или между этапами
        for item in largeArray {
            if isCancelled { return } // Важно: проверка внутри цикла
            process(item)
        }

        // 4. Финальная проверка
        guard !isCancelled else { return }
        performFinalWork()
    }
}

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

// Где-то позже:
operation.cancel() // Устанавливает isCancelled = true

2. Отмена всех операций в очереди

queue.cancelAllOperations() // Вызывает cancel() для всех операций в очереди.

3. Особенности для BlockOperation

let blockOperation = BlockOperation {
    // Блок должен самостоятельно проверять isCancelled
    if !blockOperation.isCancelled {
        performWork()
    }
}

4. Зависимости и отмена

  • Отмена операции не отменяет ее зависимости.
  • Операция, зависящая от отмененной, не будет запущена, если установлено свойство isCancelled = true у зависимости. Для этого нужно проверять isCancelled у зависимых операций вручную или использовать более сложную логику.

Ключевой принцип: Операция должна быть спроектирована так, чтобы часто проверять isCancelled и корректно завершать работу, освобождая ресурсы.