2012-11-08 102 views
1

我想挑出一些相机胶卷元数据。当我列举资产时,似乎无法检索任何信息并获得空数组。我错过了一个步骤吗?AlAssetLibrary返回空结果

我的代码:

assets = [[NSMutableArray array] init]; 

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) { 
    if(asset != NULL) { 
     [assets addObject:asset]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     }); 
    } 
}; 

void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) { 
    if(group != nil) { 
     [group enumerateAssetsUsingBlock:assetEnumerator]; 
    } 
}; 

library = [[ALAssetsLibrary alloc] init]; 

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos 
         usingBlock:assetGroupEnumerator 
        failureBlock: ^(NSError *error) { 
         NSLog(@"Failed."); 
        }];  

NSLog(@"%@", assets); //prints an empty array 
+0

感谢您的回答。还有一个问题 - 是否有一种简单的方法可以挑选在某一日期拍摄的照片,而无需列举所有资产? – HHHH

回答

4

Midhun MP是正确的,你不等待异步枚举完成。在这种情况下,您有异步块调用其他异步块,因此知道何时完成所有枚举并不容易。

如果您想知道何时完成此操作,并最终获得一个包含所有枚举资产的数组,您可以使用dispatch_groups。这里是你能做到这一点的一种方式(我已经包含多个ALAssetGroup类型表明,这可以用多个相册工作):

dispatch_group_t loadingGroup = dispatch_group_create(); 
NSMutableArray * assets = [[NSMutableArray array] init]; 
NSMutableArray * albums = [[NSMutableArray array] init]; 

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) { 
    if(index != NSNotFound) { 
     [assets addObject:asset]; 
     dispatch_async(dispatch_get_main_queue(), ^{ }); 
    } else { 
     dispatch_group_leave(loadingGroup); 
    } 
}; 


void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) { 
    if(group != nil) { 
     [albums addObject: group]; 
    } else { 
     NSLog(@"Found %d albums", [albums count]); 
     // album loading is done 
     for (ALAssetsGroup * album in albums) { 
      dispatch_group_enter(loadingGroup); 
      [album enumerateAssetsUsingBlock: assetEnumerator]; 
     } 
     dispatch_group_notify(loadingGroup, dispatch_get_main_queue(), ^{ 
      NSLog(@"DONE: ALAsset array contains %d elements", [assets count]); 
     }); 
    } 
}; 

ALAssetsLibrary * library = [[ALAssetsLibrary alloc] init]; 

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos | ALAssetsGroupAlbum 
        usingBlock:assetGroupEnumerator 
       failureBlock: ^(NSError *error) { 
        NSLog(@"Failed."); 
       }]; 

(在这个例子中,它是安全的,有不同的块加入assetsalbums因为枚举全部发生在主线程上。)

+0

很难挑出一个正确的答案,因为所有人都指出我的问题,但这是最全面的。谢谢! – HHHH

+0

使用** assetEnumerator **枚举资产时,是否应该同步访问**资产**数组。 像'@synchronized(self){[assets addObject:asset]; }' – OnTheEasiestWay

+0

3年后,这篇文章救了我,谢谢! – MarioAna

0

如果您在iOS 6上运行此,这可能是因为用户已经拒绝访问你的应用程序来访问资源库。如果是这种情况,则调用failureBlock

另请注意,usingBlock是异步调用的,因此您尝试记录assets为时尚早。您应该将NSLog语句移动到枚举块的末尾。

从文档为enumerateGroupsWithTypes:usingBlock:failureBlock:

结果通过执行枚举块通过一个接一个地给调用者。

此方法是异步的。枚举组时,可能会要求用户确认应用程序对数据的访问权限;该方法虽然立即返回。您应该使用enumerationBlock中的资产执行任何您想要的工作。

如果用户拒绝访问应用程序,或者没有应用程序被允许访问数据,则调用failureBlock。

0

您的NSLog将始终显示一个空数组,因为在完成异步枚举块之前NSLog语句将工作。

解决方案:

首先检查你的photolibrary不是空的。 然后在添加的NSLog:

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) { 
    if(asset != NULL) { 
     [assets addObject:asset]; 
     NSLog(@"Asset : %@", asset); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     }); 
    } 
};