在主线程中轮询时,enumerateGroupsWithTypes不会执行块

时间:2011-06-20 10:07:04

标签: objective-c ios objective-c-blocks alasset alassetslibrary

在iOS 4.x上我试图枚举设备上的所有照片以及何时完成,然后在同一方法中进一步处理该列表。

由于enumerateGroupsWithTypes的块在另一个线程上异步运行,我无法看到如何继续执行主线程,我保持进一步处理从开始到准备的解决方案是轮询我正在收集的照片数组直到它看到它已经完成填充,最后包含一个NSNull对象。

在iOS 4.0上它工作正常 - 轮询继续进行,因为另一个线程枚举了照片,然后在完成后继续在主线程上执行。在iOS 4.1+上,轮询是一些如何阻止其他线程执行任何块的,这样轮询就会陷入无限循环。

除了通过将进一步处理分解为枚举块可以调用的不同方法来接受枚举的异步性质之外,还有更好的方法来实现此目的吗?

奖励积分:为什么我的民意调查方法适用于4.0而不是4.1 +?

NSMutableArray *photos = [NSMutableArray new];

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
    if(result != NULL) {
        [photos addObject:result];
    }
};
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
    if(group != nil)
        [group enumerateAssetsUsingBlock:assetEnumerator];
    else
        [photos addObject:[NSNull null]];
};

ALAssetsLibrary *library = [ALAssetsLibrary new];

[library enumerateGroupsWithTypes:ALAssetsGroupAll
                       usingBlock:assetGroupEnumerator
                     failureBlock:^(NSError *error) {
                         NSLog(@"%@", error);
                     }];

// keep polling until the photos have all been enumerated
// (NSNull is the last 'photo' added)
while (![photos count] || ![[photos objectAtIndex:[photos count]-1] isEqual:[NSNull null]]);

// ... further processing ...

1 个答案:

答案 0 :(得分:1)

更好的方法是让你的块开始进一步处理(例如使用performSelectorOnMainThread:withObject:waitUntilDone:),而不是让主线程轮询它。

我无法确定为什么它在4.0中有效并在4.1中失败。在4.1中它可能在某些情况下不再是异步的(例如,当用户不需要被提示时),或者在4.1中它在开始后台任务之前等待主线程上的回调,或者在你的4.1设备或模拟器实例它试图请求许可(并挂断,因为你已经阻止了主运行循环),如果你还没有授权它在你之前的测试中访问照片库,那么它也会在4.0上失败。