Fuente
Затишна Галера | iOSКомпас 🧭1️⃣3️⃣3️⃣ Завдання 133Розкажи про механізм скасування в `Op...
680 Vistas/Alcance
2025-12-17 12:40
Mensaje №2294
#iOSКомпас 🧭1️⃣3️⃣3️⃣ Завдання 133Розкажи про механізм скасування в `Operation`З вами знову той самий автор каналу @badlinkschannel. Сподіваюсь вам ще не набридла ця ідея капітана галери про iOS розробника.🤔 В `Operation` (раніше `NSOperation`) у `Foundation` є вбудований механізм скасування, який дозволяє коректно завершити операцію, якщо вона більше не потрібна. Але важливо: скасування не перериває виконання автоматично - код усередині операції повинен сам перевіряти прапорець `isCancelled` і завершуватися.🔣 Як працює скасування `Operation`?Виклик `cancel()` лише ставить операцію в стан скасування `(isCancelled = true)`.Після цього операція не припиняється автоматично й продовжить роботу, якщо не перевірятиме `isCancelled`.Тому всередині `main()` треба робити ручні перевірки і завершувати роботу самостійно.class MyOperation: Operation { override func main() { for i in 1...10 { if isCancelled { return } print("Виконується крок \(i)") sleep(1) } }}let queue = OperationQueue()let operation = MyOperation()queue.addOperation(operation)DispatchQueue.main.asyncAfter(deadline: .now() + 3) { operation.cancel()}
🔣 Скасування асинхронних операційДля асинхронних операцій `(isAsynchronous = true)` однієї перевірки `isCancelled` недостатньо. Розробник повинен вручну оновлювати стани `isExecuting` та `isFinished`, щоб `OperationQueue` могла коректно керувати життєвим циклом операції.class AsyncOperation: Operation { private var _executing = false private var _finished = false override var isAsynchronous: Bool { true } override var isExecuting: Bool { get { _executing } set { willChangeValue(for: \.isExecuting) _executing = newValue didChangeValue(for: \.isExecuting) } } override var isFinished: Bool { get { _finished } set { willChangeValue(for: \.isFinished) _finished = newValue didChangeValue(for: \.isFinished) } } override func start() { if isCancelled { isFinished = true return } isExecuting = true executeTask() } private func executeTask() { DispatchQueue.global().asyncAfter(deadline: .now() + 3) { if self.isCancelled { self.complete() return } print("Асинхронна операція завершена") self.complete() } } private func complete() { isExecuting = false isFinished = true }}let queue = OperationQueue()let asyncOp = AsyncOperation()queue.addOperation(asyncOp)DispatchQueue.main.asyncAfter(deadline: .now() + 1) { asyncOp.cancel()}
🔣 Скасування залежних операційСкасування операції не скасовує залежні автоматично - але якщо залежність не завершиться `(isFinished = true)`, залежні просто не будуть запущені. Вони не отримають статус `isCancelled`, але не виконаються.let op1 = MyOperation()let op2 = MyOperation()op2.addDependency(op1)let queue = OperationQueue()queue.addOperations([op1, op2], waitUntilFinished: false)op1.cancel()
Якщо потрібне автоматичне скасування всього ланцюжка, це треба реалізовувати вручну.@Zatishna_Galera