Return the value specified in the GCD block

I have a value that I am extracting from a block that I would like to return in the method below. As it looks, the block is asynchronous, how can I do this?

-(UIImage*) imageAtIndex:(NSUInteger)index { UIImage *image; [self.album enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:index] options:0 usingBlock: ^(ALAsset *result, NSUInteger index, BOOL *stop) { //set image in here }]; return image; } 
+4
source share
2 answers

I have done it like this in the past, check it out.

 -(void) imageAtIndex:(NSUInteger)index //since block is async you may not be able to return the image from this method { UIImage *image; [self.album enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:index] options:0 usingBlock: ^(ALAsset *result, NSUInteger index, BOOL *stop) { //set image in here dispatch_async(dispatch_get_main_queue(), ^{ //if UI operations are done using this image, it is better to be in the main queue, or else you may not need the main queue. [self passImage:image]; //do the rest of the things in `passImage:` method }); }]; } 
+2
source

If your block is asynchronous, you cannot set the return value before you return, because the program may not have completed the asynchronous task before the method completed. Some of the best solutions:

  • If you so wish, find a synchronous method that does the same job.
    Now this is not the best choice, since your user interface will be blocked during the operation of the block.

  • Call the selector when this value is found, and invalidate the method itself.

Feel, try something like this:

 -(void) findImageAtIndex:(NSUInteger)index target:(id)target foundSelector:(SEL)foundSEL { __block UIImage *image; [self.album enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:index] options:0 usingBlock: ^(ALAsset *result, NSUInteger index, BOOL *stop) { //set image in here if ([target respondsToSelector:foundSEL]) { //If the object we were given can call the given selector, call it here [target performSelector:foundSEL withObject:image]; return; } }]; //Don't return a value } 

Then you can call it like this:

  ... //Move all your post-finding code to bar: [self findImageAtIndex:foo target:self foundSelector:@selector(bar:)]; } - (void)bar:(UIImage *)foundImage { //Continue where you left off earlier ... } 
+2
source

All Articles