Ответ
Отмена 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 и, если что, могла культурно, не разбрасывая кишки, сказать «да похуй» и завершиться. Иначе будет висеть, как манда с ушами, и жрать ресурсы.