5

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

我在使用 [ALAssetsLibrary enumerateGroupsWithTypes:] 时阅读了Cocoa 线程同步,并尝试了推荐的 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];
}
4

5 回答 5

1

您在完成枚举对象之前正在杀死您的 assetsLibrary 对象。将其移动到您的 .h 文件并在 dealloc 中释放它。

于 2011-08-21T10:44:18.053 回答
1

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

诀窍是锁定您的后台线程,直到枚举产生一个零组。此类别是如何使用它的一个示例,您可以使用类别方法作为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下载类别

于 2014-02-08T21:39:06.823 回答
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

于 2014-09-23T19:41:13.517 回答
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 同步的专辑列表时

于 2018-07-03T02:52:01.590 回答
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);
于 2018-10-10T06:39:25.507 回答