问题描述
||
我正在使用[ALAssetsLibrary enumerateGroupsWithTypes:]将ALAssets存储在数组中。由于这是一个异步操作,因此我需要等待它完成才能继续我的工作。
使用[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];
}
解决方法
我知道该线程可能已死,但我正在回答,因为这是我通过谷歌搜索降落的地方
诀窍是锁定后台线程,直到枚举产生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下载类别
, 您要在完成对对象的枚举之前将其杀死。
将其移至您的.h文件,然后在dealloc中释放它。
, 此代码块应该为您工作->
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
, dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,^{
_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_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);