Sobes.tech
Middle

Vertel me over het annuleringsmechanisme bij operaties.

sobes.tech AI

Antwoord van AI

Het annuleringsmechanisme voor operaties in iOS is gebaseerd op het gebruik van het protocol Cancellable en gerelateerde typen.

Belangrijke componenten:

  1. Cancellable-protocol: Bepaalt de vereiste om een cancel()-methode te hebben, die de annulering initieert.

    // Fragment van de definitie van het protocol
    public protocol Cancellable {
        func cancel()
    }
    
  2. AnyCancellable: Wrapper-typ die elke type dat aan Cancellable voldoet opslaat, en automatisch cancel() aanroept bij deinitialisatie. Handig voor het beheren van de levenscyclus van abonnementen/operaties.

    // Voorbeeld van gebruik
    var cancellable = AnyCancellable {
        // Annuleringsactie
        print("Operatie geannuleerd")
    }
    
    // Binnen de scope waar `cancellable` is gedefinieerd, wordt bij het verlaten `cancel()` aangeroepen
    
  3. Annulering in Combine: In het Combine-framework bieden de meeste Publisher een Subscription die het Cancellable-protocol implementeert. Bij het aanroepen van cancel() op Subscription stopt de gegevensstroom. Meestal wordt Subscription ingepakt in AnyCancellable en opgeslagen.

    // Voorbeeld in Combine
    import Combine
    
    let publisher = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var cancellable: AnyCancellable? = publisher.sink { completion in
        print("Voltooiing: \(completion)")
    } receiveValue: { date in
        print("Waarde: \(date)")
    }
    
    // Annuleren na enige tijd
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        cancellable?.cancel() // Aanroep van `cancel()` op `AnyCancellable`
        cancellable = nil // Referentie opruimen
    }
    
  4. Operation en OperationQueue: In oudere API's bestaat ook een mechanisme voor annulering. De klasse Operation heeft de methode cancel() en de eigenschap isCancelled. OperationQueue controleert deze eigenschap en plant geen geannuleerde operaties.

    import Foundation
    
    class MyOperation: Operation {
        override func main() {
            if isCancelled { // Controleer de status van annulering
                print("Operatie geannuleerd voordat deze begon")
                return
            }
    
            // Voer de taak uit
            for i in 0..<1000 {
                if isCancelled { // Controleer de status tijdens de taak
                    print("Operatie geannuleerd tijdens uitvoering")
                    return
                }
                // Zware taak of API-aanroep
                print("Stap \(i)")
            }
    
            print("Operatie voltooid")
        }
    }
    
    let queue = OperationQueue()
    let operation = MyOperation()
    
    queue.addOperation(operation)
    
    // Annuleer operatie na enige tijd
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
       operation.cancel() // Aanroep van `cancel()`
    }
    
    // Wacht op voltooiing (niet aanbevolen op de hoofdthread)
    // queue.waitUntilAllOperationsAreFinished()
    

Het annuleringsmechanisme in iOS is asynchroon en coöperatief. Het aanroepen van cancel() signaleert de intentie om de operatie/gegevensstroom te annuleren, maar de daadwerkelijke stop hangt af van hoe de operatie dit signaal verwerkt (bijvoorbeeld door isCancelled te controleren of te reageren op het annuleren van de abonnementen).

Het beheer van annuleerbare objecten (vooral AnyCancellable) wordt vaak gedaan door ze op te slaan in collecties (Set<AnyCancellable>) of objecteigenschappen, om te garanderen dat cancel() wordt aangeroepen bij deinitialisatie van de container of bij expliciet verwijderen uit de collectie.