Sobes.tech
Middle

Pověz mi o mechanismu zrušení v operacích.

sobes.tech AI

Odpověď od AI

Mechanismus zrušení operací v iOS je založen na použití protokolu Cancellable a souvisejících typů.

Hlavní komponenty:

  1. Cancellable protokol: Určuje požadavek na metodu cancel(), která spouští zrušení.

    // Fragment definice protokolu
    public protocol Cancellable {
        func cancel()
    }
    
  2. AnyCancellable: Typový obal, který uchovává jakýkoli typ odpovídající Cancellable a automaticky volá cancel() při deinitializaci. Je vhodný pro správu životního cyklu odběrů/operací.

    // Příklad použití
    var cancellable = AnyCancellable {
        // Akce zrušení
        print("Operace zrušena")
    }
    
    // V rámci scope, kde je definován cancellable, při opuštění volá `cancel()`
    
  3. V Combine: Většina publisherů poskytuje předplatné (Subscription), které implementuje protokol Cancellable. Při volání cancel() na Subscription se datový tok ukončí. Obvykle je Subscription obalena do AnyCancellable a uchovávána.

    // Příklad v Combine
    import Combine
    
    let publisher = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var cancellable: AnyCancellable? = publisher.sink { completion in
        print("Dokončení: \(completion)")
    } receiveValue: { date in
        print("Hodnota: \(date)")
    }
    
    // Zrušení po nějaké době
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        cancellable?.cancel() // Volání `cancel()` na `AnyCancellable`
        cancellable = nil // Uvolnění odkazu
    }
    
  4. Operation a OperationQueue: V starém API je také mechanismus zrušení. Třída Operation má metodu cancel() a vlastnost isCancelled. OperationQueue kontroluje tuto vlastnost a nezahajuje provádění zrušených operací.

    import Foundation
    
    class MyOperation: Operation {
        override func main() {
            if isCancelled { // Kontrola stavu zrušení
                print("Operace byla zrušena před začátkem")
                return
            }
    
            // Provádění úkolu
            for i in 0..<1000 {
                if isCancelled { // Kontrola stavu zrušení uvnitř úkolu
                    print("Operace byla zrušena během provádění")
                    return
                }
                // Těžká práce nebo volání API
                print("Krok \(i)")
            }
    
            print("Operace dokončena")
        }
    }
    
    let queue = OperationQueue()
    let operation = MyOperation()
    
    queue.addOperation(operation)
    
    // Zrušení operace po nějaké době
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
       operation.cancel() // Volání `cancel()`
    }
    
    // Čekání na dokončení (například, na hlavním vlákně to nedělat)
    // queue.waitUntilAllOperationsAreFinished()
    

Mechanismus zrušení v iOS je asynchronní a kooperativní. Volání cancel() signalizuje záměr zrušit operaci/datový tok, ale skutečné zastavení závisí na tom, jak sama operace tento signál zpracovává (například kontrolou isCancelled nebo reakcí na zrušení předplatného).

Správa zrušitelných objektů (zejména AnyCancellable) se často provádí jejich uložením do kolekcí (Set<AnyCancellable>) nebo vlastností objektů, aby bylo zajištěno volání cancel() při deinitializaci kontejneru nebo při přímém odstranění z kolekce.