Search code examples
iosiphoneobjective-cicarousel

IOS access a variable outside a block


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!


Solution

  • 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