9

Allow me to preface this by saying this is my first time using the ALAssetsLibrary. I need to access the most recent photo in the user's saved photo gallery. It seems that to do this, I have to create an ALAssetsLibrary instance and iterate over every item in the user's gallery before selecting the last image. This is always worst-case scenario. Is there a faster/better way to approach this problem?

Jacob
  • 926
  • 1
  • 14
  • 25

4 Answers4

15

You don't have to enumerate all the photos in the user's gallery. The ALAssetsGroup class has a method - (void)enumerateAssetsAtIndexes:(NSIndexSet *)indexSet options:(NSEnumerationOptions)options usingBlock:(ALAssetsGroupEnumerationResultsBlock)enumerationBlock which you can use to indicate which assets you want to enumerate.

In your case it's only the last one so set indexSet to [NSIndexSet indexSetWithIndexesInRange:NSMakeRange([group numberOfAssets]-1, [group numberOfAssets]) where group is your ALAssetsGroup.

As @mithuntnt mentioned, you can get the ALAssetsGroup for the photo library using [[assetsLibrary] enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop)

adriaan
  • 1,574
  • 14
  • 33
  • Thanks, you rock! That's just what I was looking for. – Jacob Jul 30 '11 at 16:32
  • 1
    Small bug in the above answer if you're using this. NSMakeRange([group numberOfAssets]-1, [group numberOfAssets]) should be NSMakeRange([group numberOfAssets]-1, 1) (nsmakerange's second param is the count, not the end index). Alternatively, [NSIndexSet indexSetWithIndex:[group numberOfAssets]-1] is slightly more efficient. – Ivo Jansch Oct 30 '12 at 21:38
1

What about this:

[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
    if (result) {
       *stop = YES;
       //...
    }
}];
huoxinbird
  • 520
  • 6
  • 13
0

The accepted answer doesn't appear to work if you're enumerating an ALAssetGroup that you've set a filter on (because [group numberOfAssets] returns the total assets rather then the total assets after filtering).

I used this:

typedef void(^SMKMostRecentPhotoCompletionBlock)(ALAsset *asset);

- (void)mostRecentPhotoWithCompletionBlock:(SMKMostRecentPhotoCompletionBlock)completionBlock
{
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

    __block ALAsset *mostRecentPhoto = nil;

    if (group)
    {
        [group setAssetsFilter:[ALAssetsFilter allPhotos]];
        [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {

            if (result != NULL)
            {
                mostRecentPhoto = result;
                *stop = YES;
            }

        }];
    }

    if (completionBlock)
    {
        completionBlock(mostRecentPhoto);
    }

} failureBlock:^(NSError *error) {

    if (completionBlock)
    {
        completionBlock(nil);
    }

}];

}

In your completionBlock, make sure to check that the returned ALAsset != nil.

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
Alfie Hanssen
  • 16,964
  • 12
  • 68
  • 74
0

http://developer.apple.com/library/ios/#documentation/AssetsLibrary/Reference/ALAssetsLibrary_Class/Reference/Reference.html

There is only one enumeration method. So this is the only way.

I needed the last imported photos. You can have some filter similar to this.

[[assetsLibrary] enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    if( group )
    {
        NSString * groupName = [group valueForProperty:ALAssetsGroupPropertyName];

        if( [@"Last Import" isEqualToString:groupName] )
        {
            *stop = true;

...

mithuntnt
  • 507
  • 1
  • 5
  • 17