iOS Asset Library photo browsing experiments

My photo browsing work has gone in fits and starts over the last two weeks, but I have made some progress through experimentation. Since upgrading to an iPhone 4, and the subsequent announced availability of iOS 4.2 on the iPad, I can now use the Asset Library framework in my prototypes. I want to use other photo sources eventually, but my first version will use the photo albums available on the device.

Experiments with Asset Library lead to experimenting with blocks and Grand Central Dispatch

One of features I want in my app is a photo stream that moves automatically across the device in some fashion, but still allows the user to control the pace. The first step was to build a simple prototype that browsed through the photo albums currently synced to the device.

The Asset Library framework is fairly small and handles all access to on device photos, videos, and the associated albums. Each photo or video is an “asset” in the library. The entry point is through the enumerateGroupsWithTypes:usingBlock:failureBlock: method in the ALAssetLibrary class. As you can tell by the method name, this method makes use of blocks to accomplish its work.

Objective-C blocks are very clean and crisp, taking care of otherwise messy implementation details such as automatically retaining and releasing objects referenced by the block. The syntax for the simplest executable block is:

^{}

which obviously doesn’t do very much, but clearly is not encumbered by extra baggage. A block is a closure that captures the state of any references external to the block and maintains them during the life of the block. Many languages and environments offer closures, and if you come from the Java world like I do, they are a welcome relief from the not-quite-good-enough nature of anonymous inner classes. It is very nice to be able to work with them in iOS.

Another feature of the latest versions of iOS that comes in handy with browsing the photo albums is Grand Central Dispatch (GCD). GCD was introduced to OS X in Snow Leopard, and to iOS in version 4.0. Many of the tasks that used to require creating separate threads can now be handled much easier and cleaner with GCD and blocks.

Here is one method from a very simple example that loads all the asset references on my phone into a mutable array ‘assets’ in the background while updating a simple status label on the main thread with the current asset count:

- (void) updateCount {
    self.statusLabel.text = [NSString stringWithFormat:@"Count: %u", [assets count]];;
}

- (void) loadLibrary {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(queue, ^{
        void (^assetEnumerator)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
            if(asset != NULL) {
                [assets addObject:asset];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self updateCount];
                });
            }
        };

        void (^assetGroupEnumerator)(struct ALAssetsGroup *, BOOL *) =  ^(ALAssetsGroup *group, BOOL *stop) {
            if(group != nil) {
                dispatch_async(queue, ^{
                    [group enumerateAssetsUsingBlock:assetEnumerator];
                });
            }
        };

        [library enumerateGroupsWithTypes:ALAssetsGroupAll
                               usingBlock:assetGroupEnumerator
                             failureBlock: ^(NSError *error) {
                                 NSLog(@"failure");
                             }];
    });
}

I do not completely understand all the interactions between GCD queue, the main thread, and the asset library enumeration. There is not a lot of information in Apple’s documentation about exactly what is going on, but it appears that each enumeration happens on the main thread, even if the caller is run from an asynchronous queue which is *not* on the main thread.

To ensure the loading does not tie up the main thread, and thus prevent GUI updates, I enclosed the call to “group enumerateAssetsUsingBlock…” in a block (lines 20-22) and put that block on the default queue to be run in the background as well. This particular pattern will load each asset in the background, but update the status label in the main thread properly.

Lines 12-14 illustrate the GCD method of running code on the main thread. It looks cleaner to me than calling performSelectorOnMainThread, and is certainly more flexible since it can include any code you wish.

Feedback from non-techies

In addition to experimenting with several different ideas and prototypes based on the Asset Library, I also was able to show a simple photo stream demo to an avid iPad user (my daughter!) while we were visiting my grandson last week. I think I conveyed my ideas fairly well to her, and although she doesn’t yet have an iPad (but wants one), nor does she yet have multiple thousands of photos, she is quickly heading that way. She is also the one who did much of the scanning and sorting a few years ago, so she has an idea of the pain point I am trying to address. She thought it a reasonable approach and as I turn my simplistic prototypes into a more complete app, I hope to get more detailed feedback from her and others.

360iDev Austin, November 7-10th

I finally sorted through my schedule for the fall and registered for 360iDev in Austin this November. If you are like me, and receive most of your iOS encouragement and growth virtually through the internet, you need to attend. I am as much a lone wolf as any developer out there, but the motivation and encouragement I receive from the iOS community through 360iDev keeps me coming back.

I am really looking forward to visiting with old friends and fellow iOS developers, to participate in the game jam, to learning more about iOS development and techniques for building an indie software business, and to being encouraged and motivated in my iOS development. You should register too!


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!