【问题标题】:ALAssetsLibrary enumerateGroupsWithTypes: - Thread synchronizationALAssetsLibrary enumerateGroupsWithTypes: - 线程同步
【发布时间】:2011-06-06 19:51:01
【问题描述】:

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

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

【问题讨论】:

    标签: iphone cocoa-touch nslock alassetslibrary


    【解决方案1】:

    您正在杀死您的 assetsLibrary 对象,然后才能枚举对象。 将其移至您的 .h 文件并在 dealloc 中释放。

    【讨论】:

    • 我认为这是不对的。 enumerateGroupsWithTypes 几乎肯定会为自己保留对象,直到它完成。如果你用NSLog查看assetsLibrary的retainCount,你会发现release后还是1。
    【解决方案2】:

    我知道这个帖子可能已经死了,但我正在回答它,因为这是我通过谷歌搜索登陆的地方

    诀窍是锁定你的后台线程,直到枚举产生一个 nil 组。此类别是如何使用它的一个示例,您可以使用类别方法作为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下载类别

    【讨论】:

    • 赞成!这可能没有回答我的具体问题,但它确实提供了一个重要的线索。我在文档中错过了当枚举结束时对块的最后一次调用传递一个 nil 组。
    • 谢谢,这也是我第一次错过的东西,很高兴能帮上忙!
    【解决方案3】:

    这个代码块应该适合你 -->

        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

    【讨论】:

      【解决方案4】:
      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 同步专辑列表

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-04-30
          • 1970-01-01
          • 1970-01-01
          • 2018-12-23
          • 2016-01-20
          • 1970-01-01
          相关资源
          最近更新 更多