Swiftpack.co - marcelvoss/RetryKit as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
RetryKit is a package that implements a mechanism for retrying work based on strategies and outputs.
.package(url: "https://github.com/marcelvoss/RetryKit.git", from: "0.1.2")


RetryKit is a tiny package that implements a flexible mechanism for retrying work based on strategies and outputs (and when using e.g. NSOperation is overkill).

It has been written with two principles in mind: simplicity and elegance.


RetryKit is distributed using the Swift Package Manager. To install it into a project, add it as a dependency within your Package.swift manifest:

let package = Package(
    dependencies: [
        .package(url: "https://github.com/marcelvoss/RetryKit.git", from: "0.1.0")

Then import RetryKit wherever you’d like to use it:

import RetryKit

It's that simple! 🎉


Using RetryKit is easy.

Work is being encapsulated in Task objects. These objects don't do anything else than abstracting any work, providing an output validation closure and keeping track of the number of times they have been retried. They're really simple but allow for much flexibility, as reflected by their initializer:

let task = Task<Result<String, Error>>(maximumAttempts: 5, work: { output in
    // perform any synchronous or asynchronous work
    // and execute the output closure with your result
}, outputValidation: { output in
    // perform any validation and return a flag whether a retry should be performed
    switch output {
        case .success:
            return false
        case .failure:
            return true

The output validation closure is being called during the retry process with the value of the produced output and allows for customizing the conditions under which a an attempt is being made, case-by-case. Therefore, it allows for simple but also pretty complex conditions.

Task objects are being dispatched by a Retrier object. Retrier objects are equally simple. They do have a single responsibility: dispatching tasks when appropriate (as decided by the output validation closure and the strategy.


RetryKit ships with three built-in different strategies for retrying: immediate, after(delay: TimeInterval),.custom((Int) -> TimeInterval). These strategies should cover almost every scenario.


.immediate is the easiest from all of them. All work is being retried immediately without any delay in between. You might want to use this one when many repetitive retries is not a concern.

after(delay: TimeInterval)

after(delay: TimeInterval) does basically what you would expect by reading its interface. Work is being retried after a constant delay in between attempts.

.custom((Int) -> TimeInterval)

.custom((Int) -> TimeInterval) allows for most customization out of these three. The delay between attempts is being provided/calculcated by yourself using the number of retries that have happened so far.

A custom strategy is often most useful when you care about adding some randomness to it and allows for using an exponential backoff delay between attempts.


This has been built @marcelvoss and has been inspired by a similar work that I built for the SumUp merchant application.


Stars: 9
Last commit: 5 weeks ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Submit a free job ad (while I'm testing this). The analytics numbers for this website are here.

Release Notes

21 weeks ago


  • Fix Retrier's begin completion call (#1) by @ramonilho

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics