2011-06-06 64 views
5

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

我读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]; 
} 

回答

1

你杀死你assetsLibrary对象之前它完成于enumrate的对象。 将其移至.h文件并在dealloc中释放它。

+0

我不认为这是正确的。在完成之前,enumerateGroupsWithTypes几乎可以肯定地保留它自己的对象。如果你使用NSLog来查看assetLibrary的retainCount,你会发现它在发布后仍然是1。 – 2013-02-05 06:13:08

2

我知道这个线程可能是死了,但我回答,因为这是我登陆谷歌搜索

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

@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

+0

已投票!这可能没有回答我的具体问题,但它确实提供了一个大的线索。我在文档中错过了当枚举结束时,最后一次调用该块通过一个零组。 – 2014-03-12 20:06:46

+0

谢谢,那是我第一次错过的东西,很高兴能够帮上忙! – epologee 2014-03-13 09:54:48

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您可能希望让时间从现在

1秒