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/