2016-01-20 12 views
6

Więc jestem trochę zagubiony, jak zaimplementować logikę ponowną, gdy moje żądanie przesyłania nie powiedzie się.Logika "ponownej próby" Swift na żądanie

Oto mój kod chciałbym pewne wskazówki, w jaki sposób to zrobić

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

Sprawdź moje odpowiedzi na podobne pytanie: http://stackoverflow.com/a/38720898/319805 – MNassar

Odpowiedz

14

Oto ogólne rozwiązanie, które można zastosować do dowolnej funkcji asynchronicznej, że nie posiada żadnych parametrów, z wyjątkiem tych wywołań zwrotnych. Uprościłem logikę, mając tylko wywołania zwrotne o numerach od success i failure, co nie powinno być trudne.

Zakładając więc, że funkcja jest tak:

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() 
    }) 
} 

retry funkcja dopasowania to będzie wyglądać następująco:

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) 
      } 
     }) 
} 

i można nazwać tak:

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

Powyższa próba będzie się powtórzyć trzy razy, jeśli zostanie wykonana próba połączenia z numerem startUploading. ciągle się nie udaje, inaczej zakończy się z pierwszym sukcesem.

Edytuj. Funkcje, które mają inne params może być po prostu osadzone w zamknięciu:

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

Czy mogę zapytać, co oznacza "in" w tym miejscu w "ponów próbę (3, {sukces, niepowodzenie w updateUsername (newUsername, success, failure)} "? Dzięki. – allenlinli

+2

@allenlinli' in' tutaj reprezentuje separator 'Swift' między argumentami zamknięcia a jego ciałem – Cristik

2

Oto uaktualniony odpowiedź do szybkiego 3. Dodałem też ogólny obiekt w bloku sukcesu, więc jeśli uczynić obiekt po wywołaniu sieci jest kompletny, możesz go przekazać do ostatecznego zamknięcia. Oto funkcja ponawiania:

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) 
    } 
    } 
} 

A oto w jaki sposób go używać, jeśli aktualizowany użytkownika i chciał wrócić nowy obiekt użytkownika z zaktualizowaną informacją:

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

Hi Justin, jest możliwe z użyciem tej funkcji: func DataTask (z zapytaniem: URLRequest, completionHandler: @escaping (Data ?, URLResponse ?, Błąd?) -> Void) -> URLSessionDataTask Thank – lveselovsky

Powiązane problemy