ALAssetsLibrary enumerateGroupsWithTypes: - 线程同步

时间:2011-06-06 19:51:02

标签: iphone cocoa-touch nslock alassetslibrary

我正在使用[ALAssetsLibrary enumerateGroupsWithTypes:]将ALAssets存储在数组中。由于这是一个异步操作,我需要等待它完成才能继续我的工作。

我阅读了Cocoa thread synchronisation when using [ALAssetsLibrary enumerateGroupsWithTypes:]并尝试了推荐的NSConditionLock。但是,块总是在主线程中执行,因此如果我等待使用条件锁,则主线程被阻塞并且块将不会被执行 - >我被卡住了。 我甚至尝试在新线程上运行方法loadAssets,但仍然在主线程上执行块。

我找不到真正等待枚举完成的方法。有没有办法强制块与主线程或其他任何我可以做的不同的线程?

以下是代码:

- (void)loadAssets
{
    assets = [NSMutableArray array];
    NSConditionLock *threadLock = [[NSConditionLock alloc] initWithCondition:THREADRUNNING];

    void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop)
    {
        if(result != nil)
        {
            [assets addObject:result];
        }
    };

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

        [threadLock lock];
        [threadLock unlockWithCondition:THREADFINISHED];
    };

    void (^assetFailureBlock)(NSError *) = ^(NSError *error)
    {
        [threadLock lock];
        [threadLock unlockWithCondition:THREADFINISHED];
    };

    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:assetGroupEnumerator failureBlock:assetFailureBlock];

    [threadLock lockWhenCondition:THREADFINISHED];
    [threadLock unlock];

    [assetsLibrary release];
    [threadLock release];
}

5 个答案:

答案 0 :(得分:2)

我知道这个帖子可能已经死了,但是我正在回答它,因为这是我通过Google搜索

降落的地方

诀窍是锁定后台线程,直到枚举产生一个nil-group。此类别是如何使用它的一个示例,您可以使用类别方法作为ALAssetsLibrary枚举方法的直接替换。

@implementation ALAssetsLibrary (EEEConcurrency)

- (NSUInteger)eee_enumerateGroupsLockedWithTypes:(ALAssetsGroupType)types
                                      usingBlock:(ALAssetsLibraryGroupsEnumerationResultsBlock)enumerationBlock
                                    failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock
{
    NSAssert(![NSThread isMainThread], @"This would create a deadlock (main thread waiting for main thread to complete)");

    enum
    {
        EEEAssetsLibraryDone,
        EEEAssetsLibraryBusy
    };

    NSConditionLock *assetsLibraryConditionLock = [[NSConditionLock alloc] initWithCondition:EEEAssetsLibraryBusy];

    __block NSUInteger numberOfGroups = 0;
    [self enumerateGroupsWithTypes:types
                        usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
                            enumerationBlock(group, stop);
                            if (group) numberOfGroups++;
                            if (!group || *stop)
                            {
                                [assetsLibraryConditionLock lock];
                                [assetsLibraryConditionLock unlockWithCondition:EEEAssetsLibraryDone];
                            }
                        }
                      failureBlock:^(NSError *error) {
                          failureBlock(error);
                          [assetsLibraryConditionLock lock];
                          [assetsLibraryConditionLock unlockWithCondition:EEEAssetsLibraryDone];
                      }];

    [assetsLibraryConditionLock lockWhenCondition:EEEAssetsLibraryDone];
    [assetsLibraryConditionLock unlock];

    return numberOfGroups;
}

@end

https://gist.github.com/epologee/8890692

下载类别

答案 1 :(得分:1)

在完成枚举对象之前,你要删除assetsLibrary对象。 将其移至您的.h文件并以dealloc发布。

答案 2 :(得分:0)

此代码块应该适合您 - >

    ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    __block int numberOfGroups = 0;

    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [assetsLib enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            if (group) {
                numberOfGroups++;
            }
            else {
                dispatch_semaphore_signal(sema);
            }
        } failureBlock:^(NSError *error) {
            NSLog(@"enumerateGroupsWithTypes failure %@", [error localizedDescription]);
            dispatch_semaphore_signal(sema);
        }];
    });

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    NSLog( @"number of groups is: %d", numGroups);

虽然不是DISPATCH_TIME_FOREVER,但您可能希望从现在开始一秒钟

答案 3 :(得分:0)

dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        _assetsLibrary = [[ALAssetsLibrary alloc] init];


        ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
            if (group)
            {
                if (((NSString *)[group valueForProperty:ALAssetsGroupPropertyType]).intValue == ALAssetsGroupAlbum)
                {
                    [albumSettingsList addObject:group];
                } else {
                    dispatch_semaphore_signal(sema);
                }
            }
        };

        ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {

            switch ([error code]) {
                case ALAssetsLibraryAccessUserDeniedError:
                case ALAssetsLibraryAccessGloballyDeniedError:
                    break;
                default:
                    break;
            }
            dispatch_semaphore_signal(sema);
        };

        NSUInteger groupTypes = ALAssetsGroupAlbum | ALAssetsGroupEvent | ALAssetsGroupFaces | ALAssetsGroupSavedPhotos;
        [self.assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:listGroupBlock failureBlock:failureBlock];
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

每当您想使用IOS 7获得相册列表synchoronos时

答案 4 :(得分:0)

使用dispatch_semaphore_t对其进行控制

dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll
                                 usingBlock:^(ALAssetsGroup *assetsGroup, BOOL *stop) {
                                     if (assetsGroup) {
                                         // Filter the assets group
                                         [assetsGroup setAssetsFilter:[ALAssetsFilter allAssets]];
                                         // Add assets group
                                         if (assetsGroup.numberOfAssets > 0) {
                                             // Add assets group
                                             DNAlbum *album = [DNAlbum albumWithAssetGroup:assetsGroup];
                                             [albumArray addObject:album];
                                         }
                                     }
                                     if (*stop || !assetsGroup) {
                                         dispatch_semaphore_signal(sem);
                                     }
                                 } failureBlock:^(NSError *error) {
                                     dispatch_semaphore_signal(sem);
                                 }];
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);