2012-09-27 93 views
3

我有一个iOS项目,它从数据源方法中提取图像。我希望能够从assets library(和下面的代码块这样做就好)拉图像。iOS - 从块中返回一个变量

但是,我需要这个dataSource方法返回UIImage,但是当我使用资产库方法获取图像时,图像返回到结果块中。简单地将return image放在结果块中显然不起作用。

有没有人有任何想法如何我可以从结果块内返回UIImage?我还看到了其他几个关于在块内返回图像的问题,但他们说要调用另一种方法。我 - 不幸 - 不能这样做,因为这种方法是一个nimbus数据源方法,它必须返回一个UIImage。

任何帮助或建议将不胜感激!代码如下:

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

请问您可以提供更多关于这个dataSource方法的代码吗?你上面的代码显然是功能性的,但是你说如果来自dataSource没有办法发送消息 - 我必须相信我并不是唯一不知道真正问题在这一点上的人。 –

+0

返回的图像始终为零,因为assetslibary调用是异步的。所以在'resultBlock'执行之前,返回的图像被触发。在'image = [UIImage imageWithCGImage:imageRef]'后面的'resultBlock'中放置一个'return image'似乎是非法的;' – Brett

+0

我想你必须重新加载你的架构才能在查询你的图片之前加载图片数据源。 –

回答

0

所以我想我有一个解决您的问题。这个想法是利用dispatch_group,因为你可以等待一个调度组 - 它给你一种方法来阻塞线程,直到发生什么事情。它可能需要你的数据源操作不使用主线程,但你将不得不玩这个。让我们假设实现photoAlbumScrollView的对象被称为'obj'。

  • OBJ创建一个串行调度队列(即队列)
  • 数据源发[OBJ photoAlbumScrollView]消息
  • photoAlbumScrollView做什么,现在呢,但队列返回之前等待
  • 最终块疏导队列让组完成

的代码:

__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; 

我明显没有测试这个,但是它或者其他接近它的东西应该可以工作,假设你可以在一个线程上而不是在mainThread上。

+0

这是我不能做的,因为该数据源方法需要返回一个UIImage。我错过了什么吗? – Brett

2

您应该为每个图像创建一个数组。当首次调用此数据源方法时,数组中没有该索引的图像。启动资产调用,然后返回占位符图像。块返回时,将块占位符图像替换为块中返回的资产图像。您可能需要使用GCD在主队列上执行此操作。

+0

你的意思是每个图像都有一个占位符的数组,对吧?这是一个好主意,并为您如何处理用户界面提供了很好的灵活性。 –

+0

该数组保存从块返回的图像作为缓存它们的手段。您不需要将占位符图像存储在数组中。如果图像很大,兑现它们将占用大量的内存,所以你会想要跳过这部分过程。 –

+0

如果尺寸较大,则可能需要缓存完整尺寸图像的缩略图而非整个图像。数据源方法中的加载参数可能表示它“知道”在调用方法时可能没有图像。因此,它可能提供了一种机制来在另一个调用中处理这个场景等。为了澄清,一定要更新主队列上的图像,因为块中调用的代码可能不在主线程中。 –