6

I'm trying to get a list of photo albums available in the device using the reference from here:

So far I have this in my viewDidLoad:

// Get albums
NSMutableArray *groups = [NSMutableArray new];
ALAssetsLibrary *library = [ALAssetsLibrary new];

ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
    if (group) {
        [groups addObject:group];
    }
};
NSUInteger groupTypes = ALAssetsGroupAlbum;
[library enumerateGroupsWithTypes:groupTypes usingBlock:listGroupBlock failureBlock:nil];

NSLog(@"%@", groups);

However, nothing is added to the groups array. I am expecting to see 2 items from the NSLog.

Bug
  • 2,576
  • 2
  • 21
  • 36
resting
  • 16,287
  • 16
  • 59
  • 90

2 Answers2

5

For IOS9 onwards ALAsset library has been deprecated. Instead the Photos Framework has been introduced with a new asset type called PHAsset. You can retrieve albums using PHAssetCollection class.

PHFetchResult *userAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:nil];
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAny options:nil];

PHAssetCollectionType defines the type of the albums. You can iterated the fetchResults to get each album.

[userAlbums enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop) {}];

Album in photos framework is represented by PHAssetCollection.

Greg
  • 515
  • 1
  • 8
  • 19
Gihan
  • 2,476
  • 2
  • 27
  • 33
4

It looks like the response comes in the async response listGroupBlock, but your NSLog comes right after the call. So groups will still be empty and won't be populated in the current thread yet.

What about adding the logging in listGroupBlock?

ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
    if (group) {
        [groups addObject:group];
    }
    NSLog(@"%@", groups);

    // Do any processing you would do here on groups
    [self processGroups:groups];

    // Since this is a background process, you will need to update the UI too for example
    [self.tableView reloadData];
};
ansible
  • 3,569
  • 2
  • 18
  • 29
  • Logging in the block works. I guess the problem is what you said. But how can I ensure that `groups` is populated before iterating its content? – resting Jan 15 '14 at 08:57
  • Since listGroupBlock is called from a background thread (and not the thread you created it on) you will need to do any processing on groups in `listGroupBlock`, right where we are logging it. This also means if you will need to update your UI from `listGroupBlock` too. For example, if you are displaying it in a UITableView, you will also ned to call `[tableView reloadData]` within `listGroupBlock`. Make sense? – ansible Jan 15 '14 at 14:21
  • Ok. That approach should be fine too. Thanks. – resting Jan 16 '14 at 01:13