【问题标题】:Unable to enumerate groups/results while using ALAssetsLibrary in static library在静态库中使用 ALAssetsLibrary 时无法枚举组/结果
【发布时间】:2014-01-14 07:46:54
【问题描述】:

这个问题已经解决了,但在这个问题的底部还有一个请求。毕竟我会选择一个答案。


我正在创建一个使用AssetsLibrary framework 的静态库。当我在项目中使用它来测试是否有效时。当我调用AssetsLibrary 实例的enumerateGroupsWithTypes:usingBlock:failureBlock: 方法时,它什么也不返回。

我已经尝试了-

  1. 设置断点以查看它如何运行此方法。结果它没有进入传递给usingBlock:的块,即ALAssetsLibraryGroupsEnumerationResultsBlock,或者failureBlock:。所以我一无所获。

  2. 将相同的枚举代码添加到我开头提到的项目中以尝试调用AssetsLibrary的方法。效果很好很好

  3. 测试是否被主线程阻塞,然后在主线程中运行。得到了和以前一样的结果。

对于这个问题,我找到了关于在静态库中使用媒体的其他问题的答案:https://stackoverflow.com/a/15331319/1583560,我不确定我是否遇到过同样的情况,他/她提到的媒体是包括访问AssetsLibrary,我猜这里没有。

希望有人能指点一下这个,谢谢:)


更新

这是我使用的代码 -

[[[ALAssetsLibrary alloc] init] enumerateGroupsWithTypes:ALAssetsGroupAll
                                              usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
                                                  NSLog(@"%s",__PRETTY_FUNCTION__);
                                              } failureBlock:^(NSError *error) {
                                                  NSLog(@"%s",__PRETTY_FUNCTION__);
                                              }];

静态库中的代码和测试项目中的代码是一样的,唯一不同的是我做了一个模型类来访问静态库中的AssetsLibrary

要清楚,这里是我在静态库中所做的一些更改 -

  • Target > Build Settings 中的 Build Product Path 更改为 $(PROJECT_DIR)/../build
  • 将所需的头文件移动到 Target > Build Phases > Copy Headers 中的 Project 部分
  • Target > Build Settings 中将 Skip Install 设置为 YES

环境相关-

  • OS X 10.9.1
  • Xcode 5.0.2
  • 标准架构(包括 64 位)(静态库和项目)
  • ARC

更多详情

这是我的建议,在这个静态库中制作一个易于访问的资产模型。

  • 有一个组数组来存储所有相册,这里是ALAssetsGroup,在设备中。
  • 在此模型的init 处枚举专辑并存储到组数组中。
  • 枚举照片,这是ALAssets 结果,由需要时给定的组。

而且这个模型使用单例模式。

顺便说一句,我试图在这个静态库中观察ALAssetsLibraryChangedNotification。它也不起作用。 AssetsLibrary前面有没有潜在的障碍物?


更新

我发现我在 init 我创建的模型时枚举了这些组。并且有线程使块不起作用。如果我在init 完成后触发枚举,将完美运行。而且我还找到了知道何时完成枚举(参见https://stackoverflow.com/a/13309871/1583560)以获取我存储的组数组的方法。

进一步,我仍然找不到 Apple 的文档,该文档解决了块的线程问题,为什么在 init 时不会调用它。如果有人可以为我指出,我将不胜感激:)。

【问题讨论】:

  • 您好,感谢您询问代码。我已更新问题并将其添加到原始问题的末尾。

标签: ios static-libraries alassetslibrary


【解决方案1】:

这与“无法枚举设备上的资产”无关,因为枚举 ALAssetsGroup 是异步的。


异步

根据苹果关于enumerateGroupsWithTypes:usingBlock:failureBlock:enumerateGroupsWithTypes:usingBlock:failureBlock: 的文档ALAssetsLibrary,这是一个异步方法,运行后不会得到存储在数组中的完整数据。

此方法是异步。枚举组时,可能会要求用户确认应用程序对数据的访问;但是,该方法会立即返回。您应该对 enumerationBlock 中的资产执行任何您想要的工作。


完成通知

我确实想知道什么时候完成。这样我就找到了知道进度何时完成的答案,并执行一个块(参见Create my own completion blocks in iOS)。尽管这与通知无关,但仍然给了我解决问题的提示。

postNotification: 当它到达枚举的末尾时

[_assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos  
                              usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
                                  if(group){
                                      // add into the array you are going to use
                                  }
                                  else
                                  {
                                      // the last one will be nil, 
                                      // it also means the enumeration is done
                                      // post notification then
                                      [[NSNotificationCenter defaultCenter] postNotificationName:kEnumerateGroupCompleteNotification]; 
                                  }
                              }
                            failureBlock:nil]; // leave nil here for make subject out

addObserver:selector:name:object:添加观察者重新加载数据

首先,在UICollectionViewUITableView~DataSource 协议中使用空的NSArray,这是我们在上一步中使用的保留数组。

第二,给UIViewController添加一个观察者,使用@selector传递给这个方法来触发实例的reloadData,得到刚刚枚举出来的完整数组。并且数据将显示在视图上。

// In a UIViewController's implementation 

- (void)viewDidLoad{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reloadTableView:)
                                                 name:kEnumerateGroupCompleteNotification
                                               object:nil];
}

-(void)reloadTableView:(NSNotification*) notification {

    // reloadData after receive the notification
    [_tableView reloadData];

}

结论

这就是我实现要求的方式。我只在上面提到了ALAssetsGroup,但在ALAssets 的枚举中将是相同的。

如果你想获取ALAssetsLibraryChangedNotification并重新加载数据也是一样的。

非常感谢 Ramshad 的 answer,我现在可以在我的静态库中访问 ALAssetsLibrary 作为您的建议。

【讨论】:

    【解决方案2】:

    将以下方法添加到您的类中:

    + (ALAssetsLibrary *)defaultAssetsLibrary
    {
        static dispatch_once_t pred = 0;
        static ALAssetsLibrary *library = nil;
        dispatch_once(&pred, ^{
            library = [[ALAssetsLibrary alloc] init];
        });
        return library;
    }
    

    然后修改你的代码为

    ALAssetsLibrary *assetsLibrary = [ViewController defaultAssetsLibrary];
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
     {
        [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop)
         {
            if(result)
            {
               NSLog(@"Success");
            }
         }];
    
     } failureBlock:^(NSError *error)
     {
            NSLog(@"Error loading images %@", error);
     }];
    

    【讨论】:

    • 谢谢,AssetsLibrary 使用单例是一个很好的方法,但是听了你的建议后我仍然一无所获,我将更新我制作的资产模型的更多细节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2019-03-10
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    相关资源
    最近更新 更多