2016-01-20 11 views
6

So bin ich ein bisschen verloren auf, wie eine Retry Logik implementieren, wenn meine Upload-Anfrage fehlschlagen.Swift "Retry" Logik auf Anfrage

Hier ist mein Code, den ich einige Hinweise möchte, wie man es tun

func startUploading(failure failure: (NSError) -> Void, success:() -> Void, progress: (Double) -> Void) { 
     DDLogDebug("JogUploader: Creating jog: \(self.jog)") 

     API.sharedInstance.createJog(self.jog, 
      failure: { error in 
       failure(error) 
      }, success: {_ in 
       success() 
     }) 
    } 
+0

Check out meine Antwort für eine ähnliche Frage: http://StackOverflow.com/a/38720898/319805 – MNassar

Antwort

14

Hier ist eine allgemeine Lösung, die jeder Asynchron-Funktion angewendet werden kann, die keine Parameter hat, die Rückrufe ausgenommen. Ich vereinfachte die Logik, indem ich nur success und failure Rückrufe, eine progress sollte nicht so schwer hinzuzufügen.

Also, vorausgesetzt, dass Ihre Funktion ist wie folgt:

func startUploading(success: Void -> Void, failure: NSError -> Void) { 
    DDLogDebug("JogUploader: Creating jog: \(self.jog)") 

    API.sharedInstance.createJog(self.jog, 
     failure: { error in 
      failure(error) 
     }, success: {_ in 
      success() 
    }) 
} 

A retry Funktion passende es würde wie folgt aussehen:

func retry(numberOfTimes: Int, task: (success: Void -> Void, failure: NSError -> Void) -> Void, success: Void -> Void, failure: NSError -> Void) { 
    task(success: success, 
     failure: { error in 
      // do we have retries left? if yes, call retry again 
      // if not, report error 
      if numberOfTimes > 1 { 
       retry(numberOfTimes - 1, task: task, success: success, failure: failure) 
      } else { 
       failure(error) 
      } 
     }) 
} 

und kann wie folgt aufgerufen werden:

retry(3, task: startUploading, 
    success: { 
     print("Succeeded") 
    }, 
    failure: { err in 
     print("Failed: \(err)") 
}) 

Das oben genannte wird den Anruf startUploading dreimal wiederholen, wenn es scheitert immer wieder, sonst wird beim ersten Erfolg gestoppt.

Bearbeiten. Funktionen, die andere params tun haben können einfach in einem Verschluss eingebettet werden:

func updateUsername(username: String, success: Void -> Void, failure: NSError -> Void) { 
    ... 
} 

retry(3, { success, failure in updateUsername(newUsername, success, failure) }, 
    success: { 
     print("Updated username") 
    }, 
    failure: { 
     print("Failed with error: \($0)") 
    } 
) 
+0

Kann ich fragen, was bedeutet das "in" hier in "retry (3, {Erfolg, Fehler in updateUsername (newUsername, Erfolg, Fehler)} "? Danke. – allenlinli

+2

@allenlinli' in' stellt hier 'Swift' Trennzeichen zwischen einem Abschluss Argumente und es ist Körper – Cristik

2

Hier ist eine aktualisierte Antwort für eine rasche 3. Ich so auch ein generisches Objekt in dem Erfolg Block hinzugefügt, wenn Sie ein Objekt nach Ihrem Netzwerk Anruf ist abgeschlossen, können Sie es bis zur endgültigen Schließung weitergeben. Hier ist die Wiederholungsfunktion:

func retry<T>(_ attempts: Int, task: @escaping (_ success: @escaping (T) -> Void, _ failure: @escaping (Error) -> Void) -> Void, success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) { 
task({ (obj) in 
    success(obj) 
}) { (error) in 
    print("Error retry left \(attempts)") 
    if attempts > 1 { 
    self.retry(attempts - 1, task: task, success: success, failure: failure) 
    } else { 
     failure(error) 
    } 
    } 
} 

Und hier ist, wie würden Sie es verwenden, wenn Sie einen Benutzer aktualisiert und wollten ein neues Benutzerobjekt mit den aktualisierten Informationen erhalten zurück:

NetworkManager.shared.retry(3, task: { updatedUser, failure in 
NetworkManager.shared.updateUser(user, success: updatedUser, error: failure) } 
, success: { (updatedUser) in 
    print(updatedUser.debugDescription) 
}) { (err) in 
    print(err) 
} 
+0

Hallo Justin, ist möglich verwendet es mit dieser Funktion: func dataTask (mit Anfrage: URLRequest, completionHandler: @ escaping (Daten ?, URLResponse ?, Fehler?) -> Void) -> URLSessionDataTask Vielen Dank – lveselovsky