views:

692

answers:

3

When working with Cocoa/Cocoa-Touch and the iPhone SDK, a typical convention is to build a client which speaks to a server-side web server. One common problem I face when programming is making multiple HTTP requests in sequence, sometimes up to 5-6 requests. The order in which the requests are made is not linear in which they will return. When a view is brought onto the window for which these requests are fired off, I have notifications using NSNotification letting me know when particular data is available. I'm mulling over an approach which would trigger my UI only when all the data sets are ready. Looking for good practice and insight into your approach. Are you using mutexes or something similar? Simple counters?

+1  A: 

Assuming you know all the requests that need to be made, you could store the various request objects in an array (NSMutableArray). As you receive notifications for each request, pop it off the array. When your array length equals zero, you know that all your requests have completed. You'll need to ensure that access to the array is guarded by mutexes. You'll also need to ensure that you only fire off the requests after your array is populated (lest you get a notification before your 2nd request has been inserted into the array).

Another technique, is to make the HTTP requests in another thread (performSelectorInBackground: or performSelector:onThread:), but do them synchronously. This way you know exactly when all the requests have completed and can signal the UI to update itself.

codelogic
Do them synchronously - do you mean wait for each request to finish, and only issue the next request after it has completed? Ouch.
erikprice
Synchronously in another thread and if it's applicable, for example 1) when one request depends on the output of another (eg: LoginAndGetSessionID => DoSomethingUsingSessionID => Logout) or or 2) if the requests need to be throttled (NSOperation could be used like Roger suggested).
codelogic
+1  A: 

You need to store some state alongside the NSHTTPRequest in order to link your request to your UI (or model) object or, you must be able to deduce this from the content returned by the request.

codelogic's suggestions are both examples of this pattern. NSOperation would be another.

Roger Nolan
A: 

Like codelogic already said, it’s fairly easy to maintain a seperate array or dictionary.

E.g. make sure that you properly initialize a dictionary:

notifications = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
   @"foo", @"bar",
   @"baz", @"bla",
   nil];

And then you can register for the notifications (also in the initializer):

for (NSString *key in notifications)
{
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(entityDidFetch:) name:key object:self];
}

The entityDidFetch: method can look like this:

- (void)entityDidFetch:(NSNotification *)notification
{
 @synchronized(notifications)
 {
  NSString *name = [notification name];
  [notifications removeObjectForKey:name];

  if ([notifications count] == 0)
  {
   // Final connection…
  }
 }
}

And don’t forget to release the notifications dictionary if you work on an iPhone or don’t use GC.

Rafael