Назад к вопросам
Middle
105
questionbank

Расскажи о механизме отмены в операциях.

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Механизм отмены операций в iOS основан на использовании протокола Cancellable и связанных типов.

Основные компоненты:

  1. Cancellable Protocol: Определяет требование наличия метода cancel(), который инициирует отмену.

    // Фрагмент определения протокола
    public protocol Cancellable {
        func cancel()
    }
    
  2. AnyCancellable: Тип-обертка, который хранит любой тип, соответствующий Cancellable, и автоматически вызывает cancel() при деинициализации. Удобен для управления жизненным циклом подписок/операций.

    // Пример использования
    var cancellable = AnyCancellable {
        // Действие отмены
        print("Operation cancelled")
    }
    
    // Внутри scope, где определен cancellable, при выходе он вызовет cancel()
    
  3. Отмена в Combine: В фреймворке Combine большинство Publisher'ов предоставляют подписку (Subscription), которая реализует протокол Cancellable. При вызове cancel() на Subscription, поток данных прекращается. Обычно Subscription оборачивается в AnyCancellable и хранится.

    // Пример в Combine
    import Combine
    
    let publisher = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var cancellable: AnyCancellable? = publisher.sink { completion in
        print("Completion: \(completion)")
    } receiveValue: { date in
        print("Value: \(date)")
    }
    
    // Отмена через некоторое время
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        cancellable?.cancel() // Вызов cancel() на AnyCancellable
        cancellable = nil // Очистка ссылки
    }
    
  4. Operation и OperationQueue: В старых API также существует механизм отмены. Класс Operation имеет метод cancel() и свойство isCancelled. OperationQueue проверяет это свойство и не планирует выполнение отмененных операций.

    import Foundation
    
    class MyOperation: Operation {
        override func main() {
            if isCancelled { // Проверка статуса отмены
                print("Operation cancelled before start")
                return
            }
    
            // Выполнение задачи
            for i in 0..<1000 {
                if isCancelled { // Проверка статуса отмены внутри задачи
                    print("Operation cancelled during execution")
                    return
                }
                // Тяжелая работа или вызов API
                print("Step \(i)")
            }
    
            print("Operation finished")
        }
    }
    
    let queue = OperationQueue()
    let operation = MyOperation()
    
    queue.addOperation(operation)
    
    // Отмена операции через некоторое время
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
       operation.cancel() // Вызов cancel()
    }
    
    // Ожидание завершения (для примера, в реальном приложении так делать не стоит на main потоке)
    // queue.waitUntilAllOperationsAreFinished()
    

Механизм отмены в iOS асинхронен и кооперативен. Вызов cancel() сигнализирует о намерении отменить операцию/поток данных, но фактическая остановка зависит от того, как сама операция обрабатывает этот сигнал (например, проверяя isCancelled или реагируя на отмену подписки).

Управление отменяемыми объектами (особенно AnyCancellable) часто осуществляется путем их хранения в коллекциях (Set<AnyCancellable>) или свойствах объектов, чтобы гарантировать вызов cancel() при деинициализации контейнера или при явном удалении из коллекции.