返回GCD块中设置的值

时间:2012-12-07 07:10:38

标签: iphone ios cocoa-touch objective-c-blocks grand-central-dispatch

我有一个值,我正在从一个块中检索,我想在下面的方法中返回。由于看起来块是异步的,我该如何实现呢?

-(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;
}

2 个答案:

答案 0 :(得分:2)

过去我这样做了,检查一下。

-(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
          });
     }];
}

答案 1 :(得分:2)

如果您的块是异步的,则在返回之前无法设置返回的值,因为程序在方法结束之前可能尚未完成异步任务。一些更好的解决方案是:

  1. 如果您愿意,可以找一个同样的方法来完成同样的工作 现在这可能不是最好的选择,因为你的UI会在块运行时锁定。

  2. 找到值时调用选择器,并使方法本身无效。

  3. 偶然,尝试这样的事情:

    -(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
    }
    

    然后你可以这样称呼它:

        ...
        //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
         ...
    }