使用ALAssetsLibrary枚举块强制执行命令

时间:2014-03-24 17:12:12

标签: objective-c objective-c-blocks

我正在使用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);
    }
}

2 个答案:

答案 0 :(得分:2)

至于Elad的观点,枚举方法是异步运行的,group完成后将nil

因此,与大多数异步情况一样,您应该将调用移至} 内部完成块,而不是之后。您希望在playemplayem时致电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);
}