2016-01-20 28 views
6

因此,当我的上传请求失败时,如何实现重试逻辑有点失落。按要求提供Swift“重试”逻辑

这里是我的代码,我想就如何做到这一点

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

看看我的答案对于类似的问题:http://stackoverflow.com/a/38720898/319805 – MNassar

回答

14

这里是一个可以应用到没有参数,除了回调异步的任何功能的通用解决方案的一些指导。我简化了逻辑,只有successfailure回调,progress不应该很难添加。

因此,假设你的函数是这样的:

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功能匹配它应该是这样的:

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

,可以这样调用:

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

以上将重试startUploading呼叫三次,如果它一直失败,否则会在第一次成功时停止。

编辑。这确实有其他PARAMS功能可以简单地嵌入封闭:

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

我可以问“什么是”在这里意味着在“重试(3,{成功,在更新用户名失败(新用户名,成功,失败)} “? 谢谢。 – allenlinli

+2

@allenlinli'in'这里代表'Swift'在分隔符和它的正文之间的分隔符 – Cristik

2

这里是迅速3.更新的答案,我也加入了成功的块中的通用对象,因此,如果你让一个对象的网络电话后是完整的,你可以将它传递给最终的封闭。这里是重试功能:

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

这里是你将如何使用它,如果你更新的用户,并想回到与更新的信息新的用户对象:

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, 可能与此函数一起使用:func dataTask(with request:URLRequest,completionHandler:@escaping(Data ?, URLResponse?,Error?) - > Void) - > URLSessionDataTask – lveselovsky