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

Ответ

Отмена 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 и корректно завершать работу, освобождая ресурсы.

Ответ 18+ 🔞

Ну, слушай, смотри, вот эта вся история с отменой Operation — это ж надо же, какой-то кооперативный цирк с конями, а не волшебная кнопка «стоп». Ты кричишь cancel(), а он тебе в ответ: «Хуй с горы, браток, я только флажок поднял!» И стоит такой, довольный, с флагом isCancelled = true.

А реально остановиться — это уже твоя, сука, забота. Операция должна сама, как мартышка на банане, постоянно оглядываться и спрашивать: «А не отменили ли меня, ёпта?» И если да — прикинуться дохлой и свалить, пока не прилетело.

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() // *тихо ставит флажок и смотрит на тебя*

2. Устроить тотальную зачистку в очереди

queue.cancelAllOperations() // Это как крикнуть "ВСЁ ПРОПАЛО, РАСХОДИМСЯ!" для всех операций в очереди. Каждой пошлёт cancel().

3. BlockOperation — он же особенный, блядь

let blockOperation = BlockOperation {
    // А этот товарищ вообще сам по себе. Ему надо явно свою же жопу потрогать и спросить, не отменили ли.
    if !blockOperation.isCancelled { // Смотри, какая хитрая жопа, сам себя проверяет.
        performWork()
    }
}

4. А вот с зависимостями вообще анекдот!

Представь: операция Б ждёт операцию А. Ты отменяешь А. Операция Б такая: «О, мой папаша-то флажок поднял... Ну и хуй с ним, я всё равно буду ждать, пока он полностью не сдохнет (isCancelled = true)». Если у А isCancelled стоит, Б даже не стартанёт. Но если А просто долбаёб и не проверяет флаг — Б будет ждать его вечность. Красота!

Главная мысль, которую надо выбить на лбу: Операция — не раб, она — хитрая жопа. Спроектируй её так, чтобы она постоянно оглядывалась на флаг isCancelled и, если что, могла культурно, не разбрасывая кишки, сказать «да похуй» и завершиться. Иначе будет висеть, как манда с ушами, и жрать ресурсы.