我正在使用[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];
}
答案 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
下载类别
答案 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);