我正在使用Apple的ALAssetsLibrary框架进行一些迭代。在开始播放视频之前,我需要完成此迭代。
这是缩减的示例代码,显示了我遇到的问题。
@property (nonatomic) NSMutableArray *assetsToPlay;
- (void)viewDidLoad
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
AVAsset *asset = <#Get Asset#>
[self.assetsToPlay addObject:asset];
}];
} failureBlock:nil];
[self playem]; // BUG: This code is invoked immediately. I would like it to run only after the above block iteration finished.
}
- (void)playem
{
for(AVAsset *asset in self.assetsToPlay) {
NSLog(@"%@", asset);
}
}
答案 0 :(得分:2)
至于Elad的观点,枚举方法是异步运行的,group
完成后将nil
。
因此,与大多数异步情况一样,您应该将调用移至1>} 内部完成块,而不是之后。您希望在playem
为playem
时致电group
(即您已完成枚举):
nil
答案 1 :(得分:1)
'group'在最后一次迭代中将变为'nil',因此您可以使用信号量来阻止调用线程,直到迭代完成:
- (void)syncEnumerateAssetGroups:(void(^)(ALAssetsGroup* group))block {
NSAssert(![NSThread isMainThread], @"must not run on main thread");
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self.library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos /*| ALAssetsGroupPhotoStream*/ usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (!group) {
dispatch_semaphore_signal(sema);
return;
}
if (block) {
block(group);
}
} failureBlock:^(NSError *error) {
SSLog(@"ERROR: %@", error);
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}