2012-09-27 163 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

如果尺寸較大,則可能需要緩存完整尺寸圖像的縮略圖而非整個圖像。數據源方法中的加載參數可能表示它「知道」在調用方法時可能沒有圖像。因此,它可能提供了一種機制來在另一個調用中處理這個場景等。爲了澄清,一定要更新主隊列上的圖像,因爲塊中調用的代碼可能不在主線程中。 –