Brett
Brett

Reputation: 12007

iOS - Returning a variable from a block

I have an iOS project which is pulling images from a datasource method. I would like to be able to pull the image from the assets library (and the code chunk below does this just fine).

However, I need this dataSource method to return a UIImage, but when I use the assets library methods to get the image, the image is returned in a result block. Simply putting return image in the result block obviously does not work.

Does anyone have any idea how I can have the method return a UIImage from inside the result block? I have seen several other SO questions about returning images within blocks, but they are say to call another method. I - unfortunately - can't do that because this method is a nimbus datasource method which must return a UIImage.

Any help or advice would be greatly appreciated! Code below:

- (UIImage *)photoAlbumScrollView: (NIPhotoAlbumScrollView *)photoAlbumScrollView
                     photoAtIndex: (NSInteger)photoIndex
                        photoSize: (NIPhotoScrollViewPhotoSize *)photoSize
                        isLoading: (BOOL *)isLoading
          originalPhotoDimensions: (CGSize *)originalPhotoDimensions {

    __block UIImage *image = nil;
    ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
    [assetslibrary assetForURL:[_photos objectAtIndex:photoIndex]
                   resultBlock:^(ALAsset *asset){
                       ALAssetRepresentation *rep = [asset defaultRepresentation];
                       CGImageRef imageRef = [rep fullScreenImage];
                       if (imageRef) {
                           image = [UIImage imageWithCGImage:imageRef];

                       }

                   }
                  failureBlock:^(NSError *error) {
                      //return nil;
                  }];

    return image;
}

Upvotes: 3

Views: 575

Answers (2)

David Hoerl
David Hoerl

Reputation: 41642

So I think I have a solution to your problem. The idea is to make use of a dispatch_group, since you can wait on a dispatch group - it gives you a way to block a thread until something happens. It may require that your datasource action NOT use the mainthread, but you are going to have to play with this. Lets assume that the object implementing photoAlbumScrollView is called 'obj'.

  • obj creates a serial dispatch queue (called queue)
  • datasource sends [obj photoAlbumScrollView] message
  • photoAlbumScrollView does what it does now, but before returning waits on the queue
  • the final block unblocks the queue letting the group finish

The code:

__block UIImage *image = nil;
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];

dispatch_queue_t queue = dispatch_queue_create("com.myApp.assetFetch", DISPATCH_QUEUE_SERIAL);

[assetslibrary assetForURL:[_photos objectAtIndex:photoIndex]
               resultBlock:^(ALAsset *asset){
                   ALAssetRepresentation *rep = [asset defaultRepresentation];
                   CGImageRef imageRef = [rep fullScreenImage];
                   if (imageRef) {
                       image = [UIImage imageWithCGImage:imageRef];
                   }
                   dispatch_resume(queue);
               }
              failureBlock:^(NSError *error) {
                   dispatch_resume(queue);
              }];
dispatch_suspend(queue);
dispatch_sync(queue, ^{ NSLog(@"UNSUSPEND!"); }); // ultimately a block with just a ';' in it
dispatch_release(queue);

return image;

I obviously did not test this but it or something close to it should work, assuming again that you can make this on a thread and not on the mainThread.

Upvotes: 0

Scott Ahten
Scott Ahten

Reputation: 1171

You should create an array for each image. When this data source method Is first called, you will not have an image for that index in the array. Kick off the asset call then return a place holder image. When the block returns, replace the place holder image with the asset image returned in the block. You may need to perform this on the main queue using GCD.

Upvotes: 2

Related Questions