2016-05-09 13 views
8

Ich würde gerne Methode Verkettung in meinem swift Code, wahrscheinlich Alamofire Methoden implementieren. Zum Beispiel, wenn ich meine Funktion wie verwendet unterSwift - Method Verkettung

getListForID(12).Success { 
    // Success block 
}. Failure { 
    // Failure block 
} 

Wie würde ich die Funktion getListForID schaffen?

+0

Sie ein Objekt zurückgeben kann, die 'success' und' failure' Eigenschaft hat und die 'success' Setter gibt auch, dass Sie btw kann promiseKit verwenden, das es tut http://promisekit.org/ –

+0

Sie können meinen Artikel versuchen, der genau das tut: [Verketten von asynchronen Funktionen in Swift] (https://medium.com/@jhoumuck/composing-asynchronous-functions- in-swift-acd24cf5b94a) – zeitgeist7

Antwort

7

auf den großen Punkte zu erweitern @dasblinkenlight und @Sulthan gemacht hat - hier ist ein kleines Beispiel, wie Sie Ihre Anfrage Funktion zu übernehmen einen Erfolg und Misserfolg Schließung, in der praktischen Syntax erreichen könnten, die Sie wollen.

Zuerst müssen Sie eine neue Klasse definieren, die den 'Ergebnishandler' darstellt. Dies ist, was Ihre success und failure Funktionen weitergeben werden, so dass Sie mehrere abschließende Schließungen hinzufügen können, um Ihre Abschlussblocklogik zu bilden. Sie werden es in etwa so aussehen wollen:

class ResultHandler { 

    typealias SuccessClosure = RequestHandler.Output->Void 
    typealias FailureClosure = Void->Void 

    // the success and failure callback arrays 
    private var _successes = [SuccessClosure]() 
    private var _failures = [FailureClosure]() 

    /// Invoke all the stored callbacks with a given callback result 
    func invokeCallbacks(result:RequestHandler.Result) { 

     switch result { 
      case .Success(let output): _successes.forEach{$0(output)} 
      case .Failure: _failures.forEach{$0()} 
     } 
    } 

    // remove all callbacks – could call this from within invokeCallbacks 
    // depending on the re-usability of the class 
    func removeAllCallbacks() { 
     _successes.removeAll() 
     _failures.removeAll() 
    } 

    /// appends a new success callback to the result handler's successes array 
    func success(closure:SuccessClosure) -> Self { 
     _successes.append(closure) 
     return self 
    } 

    /// appends a new failure callback to the result handler's failures array 
    func failure(closure:FailureClosure) -> Self { 
     _failures.append(closure) 
     return self 
    } 
} 

Dies ermöglicht es Ihnen, mehr Erfolg oder Misserfolg Schließungen zu definieren nach Abschluss ausgeführt werden. Wenn Sie nicht die Kapazität für mehrere Closures benötigen, können Sie die Klasse vereinfachen, indem Sie die Arrays entfernen - und stattdessen nur die zuletzt hinzugefügten Blöcke für Erfolgs- und Fehlerkomplettierung verfolgen.

Alles was Sie jetzt tun müssen, ist eine Funktion zu definieren, die eine neue ResultHandler Instanz erzeugt und dann tut eine gegebene asynchrone Anforderung, mit der invokeCallbacks Methode nach Abschluss aufgerufen wird:

func doRequest(input:Input) -> ResultHandler { 
    let resultHandler = ResultHandler() 
    doSomethingAsynchronous(resultHandler.invokeCallbacks) 
    return resultHandler 
} 

Jetzt können Sie es nennen wie dies:

doRequest(input).success {result in 
    print("success, with:", result) 
}.failure { 
    print("fail :(") 
} 

Das einzige, was zu beachten ist, Ihre doSomethingAsynchronous Funktion muss seine Fertigstellung Block zurück zum Hauptthread versenden, Thread-Sicherheit zu gewährleisten.


Voll Projekt (mit zusätzlichem Beispiel nach Verwendung): https://github.com/originaluser2/Callback-Closure-Chaining

5

Um zu verstehen, was los ist, würde es helfen, den Code neu zu schreiben, ohne die „Bequemlichkeit“ Syntax, die Sie Klammern weglassen kann, wenn ein Verschluss der letzte Parameter einer Funktion ist:

getListForID(12) 
    .Success({ /* Success block */ }) 
    .Failure({ /* Failure block */ }) 

Dies macht die Struktur des Codes hinter dieser API deutlicher:

  • der Rückgabewert von getListForID ein Objekt sein muss
  • Das Objekt muss haben zwei Funktionsgenannt 0 und Failure*
  • Beide Success und Failure benötigen einen einzelnen Parameter von Verschlusstyp
  • Beide Success und Failure Notwendigkeit

* Das Objekt nur Success Funktion haben könnte, zurück self nehmen und ein anderes Objekt mit einer einzelnen Failure-Funktion zurückgeben, aber dann können Sie die Success und Failure-Handler nicht erneut bestellen oderlöschenHandler insgesamt.

+0

Auch eine mögliche Implementierung ist ein einfacher Wrapper für zwei Arrays - ein Array von Erfolg Handler und ein Array von Fehler Handler, wenn die "Erfolg" und 'Failure' Methoden fügen den Parameter einfach dem angegebenen Array hinzu. – Sulthan

+0

@Sultan Absolut! Ich habe versucht, die Syntax zu erklären, ohne auf Details einzugehen, was in den Methoden "Erfolg" und "Fehler" passieren würde. Beide Methoden würden eine Schlussfolgerung als Argument nehmen; Was mit diesen Closures zu tun ist, hängt von den Methodenimplementierungen ab, obwohl das Speichern von Closures in separaten Arrays für die zukünftige Verwendung durchaus sinnvoll ist. – dasblinkenlight