Question

I'm trying to filter AlAssets by year and month. I can already get the dates and filter by year and month, but it's too slow with about 1000 photos. What's the best way to do it?

+ (void) loadFromLibraryByDate:(ALAssetsLibrary *)library assetType:(NSString *)type toArray:(NSMutableArray *)array onTable:(UITableView *)tableView onYear:(NSString *)year onMonth:(NSString *)mouth withDelegate:(id) delegate{

//clean passed objects
[array removeAllObjects];

// filter for the library
NSInteger groupType = ALAssetsGroupAll;



// block to enumerate thought the groups
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock =
^(ALAssetsGroup *group, BOOL *stop){
    if(group){
        [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
            if(asset){
                //                    cachedPhotos = [NSMutableDictionary new];

                if([asset valueForProperty:ALAssetPropertyType] == type){
                    if(year != nil && mouth != nil)
                    {
                        NSDate *date = [asset valueForProperty:ALAssetPropertyDate];
                        if(date.year == [year integerValue] && date.month == [mouth integerValue])
                        {
                            [array addObject:asset];
                        }
                     }
                    else if(year != nil && mouth == nil)
                    {
                        NSDate *date = [asset valueForProperty:ALAssetPropertyDate];
                        NSString *monthName = [date monthName:date.month];
                        if(date.year == [year integerValue])
                        {
                            if(![array containsObject:monthName])
                            {
                                [array addObject:monthName];
                            }
                        }
                    }
                    else
                    {
                        NSDate *date = [asset valueForProperty:ALAssetPropertyDate];
                        NSNumber *yearNum = [NSNumber numberWithInt:date.year];
                        if(![array containsObject:yearNum])
                        {
                            [array addObject:yearNum];
                        }
                    }
                }
            }
        }];
    }
    else{
        if( [delegate respondsToSelector:@selector(didFinishLoadingLibraryByDate:)] ){
            [delegate performSelector:@selector(didFinishLoadingLibraryByDate:)];
        }
        [tableView reloadData];
    }
};

// failure block, what happens if when something wrong happens when enumerating
ALAssetsLibraryAccessFailureBlock failBlock = ^(NSError *error){
    NSLog(@"Error: %@", [error localizedDescription]);

    static dispatch_once_t pred;

    dispatch_once(&pred, ^{

        dispatch_async(dispatch_get_main_queue(), ^{
            UIAlertView *libraryFailure = [[UIAlertView alloc] initWithTitle:@"Serviço de Localização" message:@"Para poder partilhar conteúdos nesta versão iOS, tem de autorizar os serviços de localização. (Definições > Serviços de Localização)" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [libraryFailure show];
            [libraryFailure release];
        });

    });

};

[library enumerateGroupsWithTypes:groupType usingBlock:listGroupBlock failureBlock:failBlock];

Any help appreciated, thanks

Was it helpful?

Solution

I think you're on the right track. There is no way I know of to filter on metadata except by enumerating the way you are doing it. Unfortunately, enumerating through asset groups is just inherently slow on iOS -- if you think 1000 is bad, try 10k or 20k assets (not at all uncommon, I have that on my carry phone right now).

One way around this (not necessarily advised, as it's a lot of work and the bug potential is very high) is to build your own database of asset timestamps. While the user is otherwise busy (with a tutorial or something), enumerate over all the assets and copy the metadata and ALAssetPropertyAssetURL to whatever format works best for you. Don't forget to listen for ALAssetsLibraryChangedNotification messages if you do this.

OTHER TIPS

You should enumerate all ALAsset first When App launching,and then filter them. Because Enumerating ALAsset from database is so slow, so you should not reenumerate them again. Therer is a notice, reenumerate ALAsset more faster then the first. Apple should optimize the library.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top