Caleb Madrigal

Programming, Hacking, Math, and Art

 

Functional programming to deal with asynchronicity in Objective-C

In the last few weeks, I've used the [ALAssetsLibrary loadImages:callback:] method to load a list of images. For what I was doing, I wanted to wait till all the images were loaded before proceeding. I found that I could solve this problem very elegantly using a recursive solution:

- (void)loadImages:(NSArray *)imageUrls loadedImages:(NSArray *)loadedImages 
                                        callback:(void(^)(NSArray *))callback
{
    if (imageUrls == nil || [imageUrls count] == 0) {
        callback(loadedImages);
    }
    else {
        NSURL *head = [imageUrls head];
        __unsafe_unretained id unretained_self = self;        
        ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:head resultBlock:^(ALAsset *asset) {
            ALAssetRepresentation *assetRepresentation = asset.defaultRepresentation;

            UIImage *image = [UIImage imageWithCGImage:assetRepresentation.fullResolutionImage 
                              scale:assetRepresentation.scale
                              orientation:(UIImageOrientation)assetRepresentation.orientation];

            [unretained_self loadImages:[imageUrls tail] loadedImages:[loadedImages 
                arrayByAddingObject:image] callback:callback];
        } failureBlock:^(NSError *error) {
            [unretained_self loadImages:[imageUrls tail] loadedImages:loadedImages callback:callback];
        }];
    }
}

In general, this scenario where you want to call a blocking method over a list of items seems to be better handled by recursion. This is just another place where functional programming proves superior in handling asynchronous tasks.

By the way, here is a reference to my NSArray+FP category which defines the head and tail code I use above.

Comments