Anthony C
Anthony C

Reputation: 1990

Serializing NSURLConnection Requests (iOS) - Use Synchronous Request?

I'm looping through a list of dates and making a request to a web server for each date in the list.

I would like each date to be processed completely before the subsequent request is sent to the server. To do this, I have set up a serial dispatch queue using GCD. Each time through the date loop, a block is added to the queue.

The problem I am having is that my NSURLConnection is set up using the standard asynchronous call. This results in requests not blocking any subsequent requests. They are thus overrunning each other.

My question: Is this a case where it would make sense for me to use the synchronous NSURLConnection (within the dispatch queue) or is there some other way to make it work using the standard asynchronous call?

Upvotes: 0

Views: 1716

Answers (2)

XJones
XJones

Reputation: 21967

There are number of ways to do this. Whatever method you choose, starting the connection needs to be tied to completion of your processing task.

  1. In each block you add to your serial queue, use a synchronous request. This is probably the quickest solution given your current implementation as long as you're ok with the limited error handling of a synchronous request.

  2. Don't use a serial queue. Start the first asynchronous connection and process the response. When processing is complete start the next asynchronous connection. Rinse and repeat.

Upvotes: 2

Andrew Madsen
Andrew Madsen

Reputation: 21383

I think that using the synchronous NSURLConnection API is a fine idea. You have a few other options. One would be to write a wrapper object around NSURLConnection that used the asynchronous NSURLConnection APIs, so you get the nice information that the asynchronous API callbacks provide, including download progress, you can easily continue to update your UI while the request is happening, but which presents its own synchronous method for doing whatever it is you need to do. Essentially, something like:

@implementation MyURLConnectionWrapper

- (BOOL)sendRequestWithError:(NSError **)error
{
    error = error ? error : &(NSError *){ nil };

    self.finishedLoading = NO;
    self.connectionError = nil;
    self.urlConnection = [][NSURLConnection alloc] init...]

    while (!self.finishedLoading) 
    {
        [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]];
    }

    if (self.connectionError != nil)
    {
        *error = self.connectionError;
        return NO;
    }

    return  YES;
}

@end

(This is all typed off the top of my head, and is heavily abbreviated, but should give you the basic idea.)

You could also do something like fire off each request in the completion delegate method for the previous one, forgoing the use of a serial dispatch queue altogether:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
    [self sendNextRequest];
}

Either way, you need to think about how to handle connection errors appropriately. I've used both approaches in different places with good success.

Upvotes: 1

Related Questions