Accessing photo library using Assets Library framework on iPhone

Up until iOS 4.0 access to user’s photos and videos on iPhone from third party applications was very limited. Pretty much all you could do is display image picker control to user, and get the image user picked or captured as a result. Anyone who wanted to create application with some sort of slide show or gallery, which would manage preexisting photos on device wasn’t in a great situation.

Luckily, when I was required to add that kind of functionality to one of the applications we were working on, Asset Library framework just became official part of SDK, so I didn’t have to go accessing the library through some questionable methods and hope that it won’t be rejected by Apple.

In this post, I’m going to go through some basics of using this framework. But before we delve deep into code, there are just some things that might require explanation. This API uses new programming device called blocks (or closures) that have been introduced with iOS 4 and Mac OS X 10.6. While the blocks are the topic for themselves, and any document explaining it in more detail could easily go over a few dozen pages, here we’ll just go through some basic explanation what they are and how to use them in this specific scenario.

As Apple puts it, block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed. What that means is that you can think of them as some sort of expanded selectors. You use the ^ operator to declare a block variable and to indicate the beginning of a block literal.

Before you start using ALAssetsLibrary, you have to add AssetsLIbrary.framework to you project, and include corresponding headers (<AssetsLibrary/AssetsLibrary.h>). After that, we can start with enumeration of different groups in users library:

void (^assetGroupEnumerator)
(struct ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop{
  if(group != nil) {
    [assetGroups addObject:group];
    NSLog(@"Number of assets in group: %d",
                 [group numberOfAssets]);
  }
};
assetGroups = [[NSMutableArray alloc] init];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSUInteger groupTypes = ALAssetsGroupAll;
[library enumerateGroupsWithTypes:groupTypes
    usingBlock:assetGroupEnumerator
    failureBlock:^(NSError *error) {NSLog(@"A problem occurred");}];
NSLog(@"Asset groups: %@", assetGroups);
[library release];

In the lines 1 – 8 we declare the block that we will use to enumerate all asset groups. It’s the block we use later in
– enumerateGroupsWithTypes:usingBlock:failureBlock:
function to fill assetGroups array with ALAssetGroup objects. Then we just select group or groups we want to access, and enumerate through them:


void (^assetEnumerator)
(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
  if(result != nil) {
    if(![assetURLDictionaries containsObject:[result valueForProperty:ALAssetPropertyURLs]]) {
      if(![[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
        [assetURLDictionaries addObject:[result valueForProperty:ALAssetPropertyURLs]];
        [assets addObject:result];
      }
    }
  }
};
assets = [[NSMutableArray alloc] init];
assetURLDictionaries = [[NSMutableArray alloc] init];
NSInteger indexOfExampleGallery = NSNotFound;
for (ALAssetsGroup *group in assetGroups) {
  if ([[group valueForProperty:ALAssetsGroupPropertyName]
      isEqualToString:@"ExampleGallery"])
  indexOfExampleGallery = [assetGroups indexOfObject:group];
}
if (indexOfExampleGallery != NSNotFound) {
  [[assetGroups objectAtIndex:indexOfExampleGallery]
  enumerateAssetsUsingBlock:assetEnumerator];
  NSLog(@"Assets %@", assets);
}
else
  NSLog(@"Gallery 'ExampleGallery' not found on device.");

Same as in past example, first we declare the block which will be executed for each asset while we enumerate them. Here, we’re interested in only one gallery, named ‘ExampleGallery’. If that group is found, we start asset enumeration, and as a result we’ll get all the ALAsset objects from the group in assets array. From ALAsset you can access one of the assets representations.

For example, if a camera provides RAW and JPEG versions of an image, the resulting asset will have two representations – one for the RAW file and one for the JPEG file. If you just want some basic info, like thumbnail, location, orientation, date you can get them from ALAsset. If you require access to metadata, raw asset data or image representations, you’ll have to fetch ALAssetRepresentation for your asset.

For more info on available properties and methods I recommend going through official ALAsset and ALAssetRepresentation class reference. Happy coding!

About Josip Maričević

Josip Maričević is working as iPhone developer at Five Minutes Ltd.
This entry was posted in Blog, iOS. Bookmark the permalink.

6 comments

  1. Just to be able to run first code snipped:
    NSMutableArray *assetGroups = [[NSMutableArray alloc] init];
    void (^assetGroupEnumerator) (ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop){
    NSLog(@”Hi”);
    if(group != nil) {
    [assetGroups addObject:group];
    NSLog(@”Number of assets in group: %d”,
    [group numberOfAssets]);
    }
    };

    assetGroups = [[NSMutableArray alloc] init];
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    NSUInteger groupTypes = ALAssetsGroupSavedPhotos;

    [library enumerateGroupsWithTypes:groupTypes
    usingBlock:assetGroupEnumerator
    failureBlock:^(NSError *error) {NSLog(@"A problem occurred");}];

    NSLog(@”Asset groups: %@”, assetGroups);
    [library release];
    [assetGroups release];

  2. Pingback: iOS ALAsset image metadata « Sarofax Technical

  3. Siema :)
    Thanks a lot, man. You have opened my eyes!
    I just stopped banging my head how to fetch particular file from the Photo Library. Thank you again.

  4. Is there a way to save images to custom library using AlAssestLibrary

  5. You may refer to the following link which shows how an Image can be saved to a custom album:
    http://www.touch-code-magazine.com/ios5-saving-photos-in-custom-photo-album-category-for-download/

  6. sorry I’m a complete beginner trying to create a Unity plugin which utilizes this code. I got all kinds of compiler errors in xcode. Is there a tutorial about this (not just code snippets, but actual entire function or file contents)? Much appreciated anyways.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>