I have the following:
__block ALAssetsGroup* album = nil;
ALAssetsLibrary* library = [ALAssetsLibrary new];
[library enumerateGroupsWithTypes: ALAssetsGroupAlbum
usingBlock:
^ (ALAssetsGroup *group, BOOL *stop) {
if (group) {
NSString* title =
[group valueForProperty: ALAssetsGroupPropertyName];
if ([title isEqualToString: @"Test1"]) {
album = group;
*stop = YES;
NSLog(@"sd%@", album.description);
}
} else { // afterwards
self.images = [self showFirstPhotoOfGroup:album]; // (oreilly, programming ios 7, ch.17)
NSLog(@"A:%d",[_images count]); // return photo count
if (!album) {
NSLog(@"%@", @"failed to find album");
return;
}
}
}
];
NSLog(@"B:%d",[_images count]);
NSLog A: correctly displays the number of items in the album as 2.
NSLog B: displays 0. In fact, it gets processed before the block!
I understand why it does this - but this is the example that Apple has supplied. Please could you tell me how I can get _images to hold it's value outside the block. The block it seems has a completely different scope.
I've been trying to load an album into an array for ages - but this block example doesn't hold it's value outside the block!
The clue to the answer lies in your own observation - NSLog B is processed before NSLog A. The method enumerateGroupsWithTypes:usingBlock:failureBlock
is documented as being asynchrnous, so it can return before anything has been enumerated. So your problem is nothing to do with values being retained etc., but simply that you are looking for the result before the work is done.
You have to design your application so that anything dependant on the enumeration is done after the enumeration has completed. The documentation for enumerateGroupsWithTypes
states that after the enumeration is finished the block will be called once more and passed nil
, you need to test for that and use it to trigger dependant actions.
HTH