NSURLSessionDataTaskRequest retry

I wanted to implement a retry mechanism for a NSURLSessionDataTask. In android I am seeing that we can simply set a retry policy for the volley request as such

myRequest.setRetryPolicy(new DefaultRetryPolicy(
       (int) TimeUnit.SECONDS.toMillis(200),
       DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
       DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

Ref: https://afzaln.com/volley/com/android/volley/DefaultRetryPolicy.html

I tried finding something similar for NSURLSessionDataTask but havent been able to find it yet. Is there any iOS SDK support for this? Or do we need to implement something like below pseudocode for retries with backoff?

self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[self callServiceWithRetries:3 timeAtStart:[NSDate date] andTimeOut:200];

id callServiceWithRetries:(int)retries
                  timeAtStart:(NSDate)timeAtStart
                  andTimeOut:(int)timeout{

    __weak __typeof(self) weakSelf = self;
    NSURLRequest *request = //create request
    NSDate *startDate = [NSDate date];
    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSDate *endDate = [NSDate date];
        NSInterval timeIntervalSinceStart = [endDate timeIntervalSinceDate:timeAtStart];
        NSInteger timeSinceStart = ((timeIntervalSinceStart %  1) * 1000);
        if (error) {
            if(retries > 0 && timeSinceStart < timeOut){
                // add delay/backoff here before making the request. To calculate the delay we can
                // use the current number of retries made. Something like exponential back off here

                [weakSelf callServiceWithRetries:retries - 1 timeAtStart:timeAtStart andTimeout:timeout];
            }
            else{
                //failure callback
            }
            return;
        }

        if(non 2xx error){
            if(retries > 0 && timeSinceStart < timeOut){
                // add delay/backoff here before making the request. To calculate the delay we can
                // use the current number of retries made. Something like exponential back off here

                [weakSelf callServiceWithRetries:retries - 1 timeAtStart:timeAtStart andTimeout:timeout];
            }
            else{
                //failure callback
            }
        }

        //success callback
    }

}

Is there any iOS SDK support for this? Or do we need to implement something like below pseudocode for retries with backoff?

There is no out out the box API support for retrying a NSURLSessionDataTask, this is something you will need to build yourself. It could be based on a counter that is set try retry a request based on a failure, or your server could direct your app to retry the request after a specific time if the actual HTTP request was successful. For example, retry this request after this date etc..

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

What Matt said but also…

I’ve seen folks construct their own retry mechanism using the retry(_:) operator in Combine.

Also, Swift’s async/await support makes the code for implementing this manually much nicer.

Unfortunately these both require Swift, and by your snippet I’m presuming that you’re working with Objective-C.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSURLSessionDataTaskRequest retry
 
 
Q