2011-06-06 13 views
5

ALAsset'leri bir dizide saklamak için [ALAssetsLibrary enumerateGroupsWithTypes:] kullanıyorum. Bu bir zaman uyumsuz işlem olduğundan, işime devam etmeden önce bitmesini beklemek zorundayım.ALAssetsLibrary enumerateGroupsWithTypes: - İş parçacığı eşitlemesi

Cocoa thread synchronisation when using [ALAssetsLibrary enumerateGroupsWithTypes:] okudum ve önerilen NSConditionLock'ı denedim. Bununla birlikte, bloklar her zaman ana iş parçacığı içinde gerçekleştirilir, böylece eğer durum kilidini kullanarak beklersem, ana iş parçacığı engellenir ve bloklar çalıştırılamaz -> Sabit kaldım. Yeni bir iş parçacığı üzerinde loadAssets yöntemini çalıştırmayı denedim, ancak yine de bloklar ana iş parçacığı üzerinde çalıştırılıyor.

Numaralandırma işleminin bitmesini beklemenin bir yolunu bulamıyorum. Blokları ana iş parçasından farklı bir iş parçacığına ya da yapabileceğim başka bir iş parçasına zorlamak için bir yol var mı?

- (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]; 
} 

cevap

1

o nesneleri enumrate için bitmiş önce size assetsLibrary nesnesini öldürüyor:

İşte kod. .h dosyasına taşıyın ve dealloc içinde bırakın.

+0

Bunun doğru olduğunu düşünmüyorum. enumerateGroupsWithTypes, neredeyse tamamlanana kadar nesneyi kendisi için korur. RetainCount of assetsLibrary öğelerini görmek için NSLog kullanıyorsanız, yayınlandıktan sonra hala 1 olduğunu görürsünüz. –

2

Ben Konuyu muhtemelen ölmüştür biliyorum ama hile numaralandırma bir nil-grup oluşturur dek arka plan iş parçacığı kilit etmektir

Googling indi budur çünkü o cevap veriyorum. Bu kategori, nasıl kullanılacağına bir örnektir; kategori yöntemini, ALAssetsLibrary numaralandırma yönteminin bir drop-in yedeği olarak kullanabilirsiniz.

@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

Yukarı oyla! Bu benim özel soruma cevap vermemiş olabilir, ancak büyük bir ipucu verdi. Dokümanlarda, sayım sona erdiğinde bloğa yapılan son çağrıya bir nil grubu geçtiğini kaçırdım. –

+0

Teşekkürler, bu benim ilk defa kaçırdığım bir şeydi, yardım etmekten memnunum! – epologee

0

de kategorisini indirin Bu kod yığın sizin için çalışması gerekir ->

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); 

yerine DISPATCH_TIME_FOREVER ait artık

gelen seferinde bir saniye yapmak isteyebilirsiniz rağmen
İlgili konular