Sobes.tech
Middle

Реци ми о механизму отказивања у операцијама.

sobes.tech АИ

Одговор од АИ

Mehanizam otkazivanja operacija u iOS zasniva se na korišćenju protokola Cancellable i povezanih tipova.

Glavne komponente:

  1. Cancellable protokol: Definiše zahtev za metodom cancel(), koja inicira otkazivanje.

    // Fragment definicije protokola
    public protocol Cancellable {
        func cancel()
    }
    
  2. AnyCancellable: Tip-omot, koji čuva bilo koji tip koji odgovara Cancellable, i automatski poziva cancel() pri deinitializaciji. Koristan je za upravljanje životnim ciklusom pretplata/operacija.

    // Primer upotrebe
    var cancellable = AnyCancellable {
        // Akcija otkazivanja
        print("Operacija otkazana")
    }
    
    // U okviru scope-a gde je definisan cancellable, pri izlasku će pozvati `cancel()`
    
  3. U Combine: Većina Publisher-a pruža pretplatu (Subscription), koja implementira protokol Cancellable. Pri pozivu cancel() na Subscription, tok podataka se prekida. Obično se Subscription obavija u AnyCancellable i čuva.

    // Primer u Combine
    import Combine
    
    let publisher = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var cancellable: AnyCancellable? = publisher.sink { completion in
        print("Završetak: \(completion)")
    } receiveValue: { date in
        print("Vrednost: \(date)")
    }
    
    // Otkaži nakon određenog vremena
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        cancellable?.cancel() // Poziv `cancel()` na `AnyCancellable`
        cancellable = nil // Uklanjanje reference
    }
    
  4. Operation i OperationQueue: U starijem API-ju takođe postoji mehanizam za otkazivanje. Klasa Operation ima metodu cancel() i svojstvo isCancelled. OperationQueue proverava ovo svojstvo i ne planira izvršenje otkazanih operacija.

    import Foundation
    
    class MyOperation: Operation {
        override func main() {
            if isCancelled { // Provera statusa otkazivanja
                print("Operacija otkazana pre početka")
                return
            }
    
            // Izvršavanje zadatka
            for i in 0..<1000 {
                if isCancelled { // Provera statusa otkazivanja unutar zadatka
                    print("Operacija otkazana tokom izvršenja")
                    return
                }
                // Težak rad ili API poziv
                print("Korak \(i)")
            }
    
            print("Operacija završena")
        }
    }
    
    let queue = OperationQueue()
    let operation = MyOperation()
    
    queue.addOperation(operation)
    
    // Otkazivanje operacije nakon određenog vremena
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
       operation.cancel() // Poziv `cancel()`
    }
    
    // Čekanje na završetak (za primer, ne bi trebalo raditi na main thread-u)
    // queue.waitUntilAllOperationsAreFinished()
    

Mehanizam otkazivanja u iOS je asinhroni i kooperativni. Poziv cancel() signalizira nameru da se otkaže operacija/tok podataka, ali stvarno zaustavljanje zavisi od toga kako sama operacija obrađuje taj signal (npr. proverom isCancelled ili reagovanjem na otkazivanje pretplate).

Upravljanje objektima koji se mogu otkazati (posebno AnyCancellable) često se vrši njihovim čuvanjem u kolekcijama (Set<AnyCancellable>) ili svojstvima objekata, kako bi se osiguralo pozivanje cancel() pri deinitializaciji kontejnera ili pri eksplicitnom brisanju iz kolekcije.