You might utilize a dispatch group, as you likely had in mind:
- (void) loadViewsWithCompletion:(completion_t)completionHandler {
ALAssetsLibrary* library = [ALAssetsLibrary new];
dispatch_group_t group = dispatch_group_create();
while ([rs next]) {
dispatch_group_enter(group);
[library assetForURL:url resultBlock:^(ALAsset *asset) {
UIImage* img = [[UIImage imageWithCGImage:asset.aspectRatioThumbnail] retain];
dispatch_async(dispatch_get_main_queue(), ^{
//create views and add to container view
...
dispatch_group_leave(group);
});
} failureBlock:^(NSError *error) {
NSLog(@"failed to load image");
dispatch_group_leave(group);
}];
i++;
}
[library release];
if (completionHandler) {
dispatch_group_notify(group, ^{
completionHandler(someResult);
});
}
... release dispatch group if not ARC
}
The code might have a potential issue though:
Since you asynchronously load images, they may be loaded all in parallel. This might consume a lot of system resources. If this is the case, which depends on the implementation of the asset loader method assetForURL:resultBlock:failureBlock:
, you need to serialize your loop.
Note: Method assetForURL:resultBlock:failureBlock:
may already ensure that access to the asset library is serialized. If the execution context of the completion block is also a serial queue, [UIImage imageWithCGImage:asset.aspectRatioThumbnail]
will be executed in serial. In this case, your loop just enqueues a number of tasks - but processes only one image at a time and you are safe.
Otherwise, if method assetForURL:resultBlock:failureBlock:
runs in parallel, and/or the block executes an a concurrent queue - images might be loaded and processed in parallel. This can be a bad thing if those images are large.