For my Spotify hackweek project I’ve been prototyping something with the Spotify iOS SDK. One of the things I want to do is get a list of track data for a series of albumns.

It’s cool, except that I when I currently loop through all my albumns, and incrementally get the track information, I don’t have an elegant way of knowing when my last asynchronous call completes in my for loop.

iKenndac showed me a really cool recursive pattern for handling this.

Basically instead of doing this:

for (each album)
   make an asynchronous call

! And then try to detect when the last one completes.

Do this instead

[self fillAlbumsRecursively:albums withSession:session finished:^{
    [self startGame];
}];


-(void)fillAlbumsRecursively:(NSArray *)albums withSession:(SPTSession *)session finished:(dispatch_block_t)finalCallback {
    
    if (albums.count == 0) {
        finalCallback();
        return;
    }
    
    NSMutableArray *mutableAlbums = [albums mutableCopy];
    SPTPartialAlbum *album = [mutableAlbums firstObject];
    [mutableAlbums removeObjectAtIndex:0];
    
    [SPTRequest requestItemFromPartialObject:album withSession:session callback:^(NSError *error, id object) {
        // Probably handle an error?
        [self.fullAlbums addObject:object];
        [self fillAlbumsRecursively:mutableAlbums withSession:session finished:finalCallback];
    }];

}

The pattern is to instead of loop, create a method that creates a copy of the collection you are looping over (albumns in this case), and then recursively call that say method, removing the album collection item you are making your distributed call on each time.

So it’s like I have 10 albums, I am going to do my async call requestItemFromPartialObject that I need to wait to complete, but when it does I am going to collect the result

        [self.fullAlbums addObject:object];

And then call it again with my mutated collection (which will be one less than it was before).

I keep doing this recursively until I am done. And that point I can be assured that my collection has been emptied, I have all my data, and I am free to do whatever I wanted to do once all my network calls have completed.

Very cool hack. Saved me some messy code. Thanks again iKenndac for sharing.