Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple async webservice requests NSURLConnection iOS

I have a problem that Im not sure how to tackle. I can without any problem make requests to the REST service when passing a single request.

My problem now is at based on that respons i get some values including ID´s. All ID´s retrieved will then need make another request to collect new information.

My guess is to load all the specific request in a array or dictionary and create request from that. Anyone have some useful tips regarding this? The information retrieved will then populate a UITableView.

like image 753
Silversnail Avatar asked Oct 11 '22 01:10

Silversnail


1 Answers

I suggest you use a Sync-Async Pattern on this problem.

You need to implement two synchronous methods:

// Fetch the array of ID's
-(NSArray*)fetchItemIDsWithError:(NSError**)error;

// Fetch the item for a ID
-(Item*)fetchItemForID:(NSString*)itemID error:(NSError**)error;

Implementing these using synchronous code is easy and testable. You can use simple methods like dataWithURL…, stringWithContentsOfURL…, sendSynchronousRequest…, or ASIHTTPrequest with ease, and write straight forward unit tests for this. The code will also be extremely easy to maintain and extend, compare to how concurrent code usually ends up.

Now to step two, create an asynchronous wrapper, I would use a delegate and a method signature like this:

@protocol FetchItemsDelegate <NSObject>
-(void)didFetchItems:(NSArray*)array;
-(void)failedFetchItemsWithError:(NSError*)error;
@end

-(void)fetchItemsWithAsyncDelegate:(id<FetchItemsDelegate>)delegate;

You already have all the code that do what you need, so all you have to do is impelemnt the asynchronious parts. This code will be well sepearated and straight forward. Probaly not more than this:

-(void)fetchItemsWithAsyncDelegate:(id<FetchItemsDelegate>)delegate;
{
    [self performSelectorInBackground:@selector(backgroundFetchItemsWithDelegate:)
                           withObject:delegate];      
}

-(void)backgroundFetchItemsWithDelegate:(id<FetchItemsDelegate>)delegate;
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    BOOL success = YES;
    NSMutableArray* items = [NSMutableArray array];
    NSError* error = nil;
    NSArray* itemIDs = [self fetchItemIDsWithError:&error];
    if (itemIDs) {
        for (NSString* itemID in itemIDs) {
           Item* item = [self fetchItemForID:itemID
                                       error:&error];
           if (item) {
               [items addObject:item];
           } else {
               success = NO;
               break;
           }
        }
    } else {
        success = NO;
    }
    if (success) {
        [delegate performSelectorOnMainThread:@selector(didFetchItems:)
                                   withObject:[NSArray arraiWithArray:items]
                                waitUntilDone:NO];
    } else {
        [delegate performSelectorOnMainThread:@selector(failedFetchItemsWithError)
                                   withObject:error
                                waitUntilDone:NO];
    }
    [pool release];
}

I have written a longer blog post on this topic here: http://blog.jayway.com/2011/04/28/sync-asyn-pair-pattern-easy-concurrency-on-ios/

like image 62
PeyloW Avatar answered Oct 14 '22 03:10

PeyloW