2011-06-06 25 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秒