Ответ 1
Здесь общее решение, которое может быть применено к любой асинхронной функции, которая не имеет параметров, за исключением обратных вызовов. Я упростил логику, имея только success
и failure
, progress
не должен быть таким сложным.
Итак, предположим, что ваша функция выглядит следующим образом:
func startUploading(success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
DDLogDebug("JogUploader: Creating jog: \(self.jog)")
API.sharedInstance.createJog(self.jog,
failure: { error in
failure(error)
}, success: {_ in
success()
})
}
Соответствующая функция retry
может выглядеть так:
func retry(times: Int, task: (success: @escaping () -> Void, failure: @escaping (Error) -> Void) -> Void, success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
task(success: success,
failure: { error in
// do we have retries left? if yes, call retry again
// if not, report error
if times > 0 {
retry(times - 1, task: task, success: success, failure: failure)
} else {
failure(error)
}
})
}
и можно назвать так:
retry(times: 3, task: startUploading,
success: {
print("Succeeded")
},
failure: { err in
print("Failed: \(err)")
})
Выше будет повторять вызов startUploading
три раза, если он продолжает сбой, в противном случае остановится при первом успехе.
Редактировать Функции, которые имеют другие параметры, могут быть просто встроены в замыкание:
func updateUsername(username: String, success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
...
}
retry(times: 3, { success, failure in updateUsername(newUsername, success, failure) },
success: {
print("Updated username")
},
failure: {
print("Failed with error: \($0)")
}
)