2017-01-01 4 views
0

Ich habe ein Szenario, wo ich drei verschiedene asynchrone Aufgaben parallel ausführen möchte. Sobald alle drei Aufgaben abgeschlossen sind, möchte ich, dass die aufrufende Methode dies erkennt und ihren eigenen Beendigungshandler aufruft.Pooling Completion Handler zusammen, so dass die Methode abgeschlossen ist, sobald mehrere Schließungen ausgeführt werden

Hier ist eine sehr vereinfachte Version der Logik für diese:

class ViewController: UIViewController { 
    func doTasks(with object: Object, completionHandler:() -> Void) { 
     // Once A, B & C are done, then perform a task 
     wrapupTask() 
     // When task is complete, call completionHandler 
     completionHandler() 
    } 
} 

fileprivate extension ViewController { 
    func taskA(with object: Object, completionHandler:() -> Void) { 
     // Do something 

     completionHandler() 
    } 

    func taskB(with object: Object, completionHandler:() -> Void) { 
     // Do something 

     completionHandler() 
    } 

    func taskC(with object: Object, completionHandler:() -> Void) { 
     // Do something 

     completionHandler() 
    } 
} 

ich leicht zusammen die Handler-Kette könnte, aber dann wird die Aufgabe übernehmen wahrscheinlich länger und der Code wird saugen.

Ein weiterer Punkt I galt ein einfacher Zähler, die jedes Mal, wenn eine Aufgabe abgeschlossen erhöht, und dann, sobald es 3 schlagen, würde die wrapupTask dann() aufrufen, über das so etwas wie:

var count: Int { 
    didSet { 
     if count == 3 { 
     wrapupTask() 
     } 
    } 
} 

Eine weitere Option Ich habe Es wird in Betracht gezogen, eine Operationswarteschlange zu erstellen und dann die Tasks in diese zu laden, mit einer Abhängigkeit, wann ich meine Nachbearbeitungsaufgabe ausführen soll. Sobald die Warteschlange leer ist, ruft sie den Beendigungshandler auf. Dies scheint jedoch mehr Arbeit zu sein, als ich für das, was ich erreichen möchte, bevorzuge.

Meine Hoffnung ist, dass es etwas besseres gibt, das ich gerade vermisse.

+3

Haben Sie ['DispatchGroup'] (https://developer.apple.com/reference/dispatch/dispatchgroup) ausgewählt? – OOPer

+0

@OOPer Beat mich dazu. :) Beachten Sie auch, CodeBender, dass Operationswarteschlange auch keine schlechte Lösung ist. – matt

Antwort

5

Nur um herauszufinden, was OOPer gesagt hat, suchen Sie nach DispatchGroup. Im Folgenden werden die Anrufe an taskA, taskB und taskC sind Pseudo-Code, aber alles andere ist real:

func doTasks(with object: Object, completionHandler:() -> Void) { 
    let group = DispatchGroup() 
    group.enter() 
    taskA() { 
     // completion handler 
     group.leave() 
    } 
    group.enter() 
    taskB() { 
     // completion handler 
     group.leave() 
    } 
    group.enter() 
    taskC() { 
     // completion handler 
     group.leave() 
    } 
    group.notify(queue: DispatchQueue.main) { 
     // this won't happen until all three tasks have finished their completion handlers 
     completionHandler() 
    } 
} 

Jeder enter von einem leave am Ende des asynchronen Abschluss Handler abgestimmt ist, und nur dann, wenn Sind alle Übereinstimmungen tatsächlich ausgeführt, fahren wir mit dem Abschlussverarbeiter notify fort.

+0

Das ist, was ich gesucht habe - danke beides! – CodeBender

+0

Funktioniert dies, wenn ich einen Completion-Handler in einem Completion-Handler innerhalb einer Task habe? –

+0

Niemals die Frage stellen. Ich habe es zur Arbeit gebracht, indem ich eine zweite Gruppe gebildet habe. –

Verwandte Themen