Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retry a block based URL Request

I am fetching data using iOS7's new URL request methods, like so:

NSMutableURLRequest *request = [NSMutableURLRequest
    requestWithURL:[NSURL URLWithString:[self.baseUrl 
    stringByAppendingString:path]]];

NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
    NSUInteger responseStatusCode = [httpResponse statusCode];

    if (responseStatusCode != 200) { 
        // RETRY (??????) 
    } else       
        completionBlock(results[@"result"][symbol]);
}];
[dataTask resume];

Unfortunately, from time to time I get HTTP responses indicating the server is not reachable (response code != 200) and need to resend the same request to the server.

How can this be done? How would I need to complete my code snippet above where my comment // RETRY is?

In my example I call the completion block after a successful fetch. But how can I send the same request again?

Thank you!

like image 362
AlexR Avatar asked May 05 '14 17:05

AlexR


2 Answers

Put your request code in a method and call it again in a dispatch_async block ;)

- (void)requestMethod {

    NSMutableURLRequest *request = [NSMutableURLRequest
                                    requestWithURL:[NSURL URLWithString:[self.baseUrl
                                                                         stringByAppendingString:path]]];

    __weak typeof (self) weakSelf = self;
    NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        NSUInteger responseStatusCode = [httpResponse statusCode];

        if (responseStatusCode != 200) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{
                [weakSelf requestMethod];
            });
        } else       
            completionBlock(results[@"result"][symbol]);
    }];
    [dataTask resume];

}
like image 53
Matteo Gobbi Avatar answered Oct 19 '22 09:10

Matteo Gobbi


It is better to have a retry counter to prevent your method from running forever:

- (void)someMethodWithRetryCounter:(int) retryCounter
{
    if (retryCounter == 0) {
        return;
    }
    retryCounter--;

    NSMutableURLRequest *request = [NSMutableURLRequest
                                    requestWithURL:[NSURL URLWithString:[self.baseUrl
                                                                         stringByAppendingString:path]]];

     __weak __typeof(self)weakSelf = self;

    NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        NSUInteger responseStatusCode = [httpResponse statusCode];

        if (responseStatusCode != 200) {
            [weakSelf someMethodWithRetryCounter: retryCounter];
        } else
            completionBlock(results[@"result"][symbol]);
    }];
    [dataTask resume];
}

It should be called following way:

[self someMethodWithRetryCounter:5];
like image 30
Avt Avatar answered Oct 19 '22 08:10

Avt