Iphone AlassetLibrary enumerateGroupsWithTypes:-线程同步

Iphone AlassetLibrary enumerateGroupsWithTypes:-线程同步,iphone,cocoa-touch,nslock,alassetslibrary,Iphone,Cocoa Touch,Nslock,Alassetslibrary,我正在使用[ALAssetsLibrary enumerateGroupsWithTypes:]将ALAssets存储在数组中。由于这是一个异步操作,我需要等待它完成后才能继续工作 我阅读并尝试了推荐的NSConditionLock。但是,块始终在主线程中执行,因此如果我使用conditionlock等待,主线程将被阻塞,块将不会执行->我被卡住了。 我甚至尝试在一个新线程上运行loadAssets方法,但块仍然在主线程上执行 我找不到真正等待枚举完成的方法。有没有一种方法可以将块强制到与主线程

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

我阅读并尝试了推荐的NSConditionLock。但是,块始终在主线程中执行,因此如果我使用conditionlock等待,主线程将被阻塞,块将不会执行->我被卡住了。 我甚至尝试在一个新线程上运行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];
}

在完成对象枚举之前,您正在终止AssetLibrary对象。 将它移动到您的.h文件中,并在dealloc中释放它。

我知道这个线程可能已经死了,但我回答它是因为这是我通过谷歌搜索登陆的地方

诀窍是锁定后台线程,直到枚举产生一个nil组。此类别是如何使用它的一个示例,您可以使用category方法作为
AlassetLibrary
枚举方法的替代品

@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

下载类别此代码块应该适合您-->

虽然你不想永远分配时间,但你可能希望从现在开始的一秒钟内分配时间

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上获得专辑列表同步,请使用dispatch\u信号灯\u 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);

我认为这是不对的。enumerateGroupsWithTypes几乎肯定会保留对象本身,直到完成为止。如果您使用NSLog查看assetsLibrary的重新计数,您将看到它在release.Up之后仍然是1!这可能没有回答我的具体问题,但它确实提供了大量线索。我在文档中错过了当枚举结束时,最后一次对块的调用传递了一个nil组。谢谢,这也是我第一次错过的,很高兴能提供帮助!
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);