1

在 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 ...
4

1 回答 1

1

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

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

于 2011-06-20T10:18:38.367 回答