获取已保存照片的块值

时间:2013-07-24 20:48:30

标签: ios objective-c photos

上一篇:我正试图在相机胶卷中获取照片数量,我开始使用积木但是遇到了一些困难。

现在: 这是我更新的代码,我正在使用异步行为,但在我的块有机会完成之前返回一个值。

#import "CoverViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>


@interface CoverViewController () <UITextFieldDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

@property(nonatomic, weak) IBOutlet UICollectionView *collectionView;

@property (assign) NSUInteger numberOfPhotos;


@end



@implementation CoverViewController


@synthesize CoverView;


- (void)viewWillAppear:(BOOL)animated
{
    NSLog(@"viewWillAppear");
    [self beginLoadingPhotoInfo];
}




//Photo collection info
- (void)beginLoadingPhotoInfo {
    NSLog(@"loaded beginloadingphotoinfo");
    __weak CoverViewController *__self = self;
    [self PhotoCount:^(NSUInteger photoCount) {
        __self.numberOfPhotos = photoCount;
    }];
    //[__self.CoverView reloadData];
}

- (void)PhotoCount:(void(^)(NSUInteger))completionBlock {

    NSLog(@"photo count start");
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    __block NSInteger result = 0;


    void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop){
        if(group != nil) {
            NSLog(@"if");
            result += [group numberOfAssets];
            NSLog(@"enum: %d", result);
        }
        else {
            NSLog(@"else");
            //nil means we are done with enumeration
            if (completionBlock) {
                completionBlock(result);
            }
        }
    };

    [library enumerateGroupsWithTypes: ALAssetsGroupSavedPhotos
                           usingBlock:assetGroupEnumerator
                         failureBlock:^(NSError *error) {NSLog(@"Problems");}
     ];

    NSLog(@"result: %u", result);
}




// Layout of collection


//Number of cells in collection
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {

    NSLog(@"returned number: %d", self.numberOfPhotos);
    return self.numberOfPhotos;
}


@end

我添加了与coverviewcontroller.h文件相关的所有内容,但代码似乎是在块完成之前加载的。这是我尝试找到错误,它显示photoCount在我的块完成之前返回0。

2013-07-27 21:16:00.986 slidr[1523:c07] viewWillAppear
2013-07-27 21:16:00.987 slidr[1523:c07] loaded beginloadingphotoinfo
2013-07-27 21:16:00.987 slidr[1523:c07] photo count start
2013-07-27 21:16:00.988 slidr[1523:c07] result: 0
2013-07-27 21:16:00.989 slidr[1523:c07] returned number: 0
2013-07-27 21:16:01.012 slidr[1523:c07] if
2013-07-27 21:16:01.013 slidr[1523:c07] enum: 3
2013-07-27 21:16:01.014 slidr[1523:c07] else

任何想法?

1 个答案:

答案 0 :(得分:1)

您正在混合和匹配同步和异步方法。有两种可能的方法。

  1. 通过传递完成块使您的photoCount方法异步返回。

    - (void)PhotoCount:(void(^)(NSUInteger))completionBlock {
    
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        __block NSInteger result = 0;
    
        void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop){
            if(group != nil) {
                if([[group valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) {
                    result += [group numberOfAssets];
                }
            } else {
                // nil group signals we're done with enumeration
                if (completionBlock) {
                    completionBlock(result);
                }
            }
        };
    
        [library enumerateGroupsWithTypes: ALAssetsGroupSavedPhotos
                               usingBlock:assetGroupEnumerator
                             failureBlock:^(NSError *error) {NSLog(@"Problems");}
         ];
    }
    
    1. 阻止当前线程,直到操作完成。这在交互式用户应用程序中通常不是一个好主意。如果你这样做,你应该重新考虑这部分应用程序的结构:

      - (NSUInteger)PhotoCount {
      
          ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
          __block NSInteger result = 0;
      
          dispatch_semaphore_t blockSemaphore = dispatch_semaphore_create(0);
      
          void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop){
              if(group != nil) {
                  if([[group valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) {
                      result += [group numberOfAssets];
                  }
              } else {
                  // nil group signals we're done with enumeration
                  dispatch_semaphore_signal(blockSemaphore);
              }
          };
      
          [library enumerateGroupsWithTypes: ALAssetsGroupSavedPhotos
                                 usingBlock:assetGroupEnumerator
                               failureBlock:^(NSError *error) {NSLog(@"Problems");}
           ];
      
          dispatch_semaphore_wait(blockSemaphore, DISPATCH_TIME_FOREVER);
      
          NSLog(@"%u", result);
          return result;
      }
      
    2. 您还以我完全不理解的方式使用resultBlock变量,所以我从答案中省略了它。

      为了清楚起见,我不会选择选项2.它会导致应用程序的响应性显着延迟,特别是如果你在主线程上调用它,特别是如果用户有一个大的资产库。

      使用块进行编程的一个好处是,您可以推迟工作,直到获得完成工作所需的所有信息。据推测,你将改变一些UI元素以响应这个数字的结果。将代码放在您传递给上述方法的完成块中。或者更好的是,将代码放入一个然后从块中调用的方法。


      要继续使用异步方法,在集合视图控制器中,您需要一个预先计算此数字的方法,可能是在控制器加载时:

      @property (assign) NSUInteger numberOfPhotos;
      
      
      - (void)beginLoadingCollectionInformation {
          __weak <<<Type of Self>>> *__self = self;
          [self PhotoCount:^(NSUInteger photoCount) {
              __self.numberOfPhotos = photoCount;
              [__self.collectionView reloadData];
          }];
      }
      
      - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
          return self.numberOfPhotos;
      }
      

      如果您可以在视图出现之前将照片计数信息设置到您的班级,那可能是理想的选择。否则,您必须在之后插入内容。这不是理想的,在这种情况下,这并不完全是我要做的。但是这个问题开始偏离数据源,委托模式和应用程序架构 - 远远超出了方法的同步和异步返回值的问题。

      希望有所帮助。


      最后一句话回答了我认为你问的最后一个问题。更改您的数据重新加载调用,以便它在完成块中发生:

      //Photo collection info
      - (void)beginLoadingPhotoInfo {
          NSLog(@"loaded beginloadingphotoinfo");
          __weak CoverViewController *__self = self;
          [self PhotoCount:^(NSUInteger photoCount) {
              __self.numberOfPhotos = photoCount;
              [__self.CoverView reloadData];
          }];
      }