ALAssetsLibrary,等到assetForURL完成

时间:2014-03-18 10:03:52

标签: ios iphone objective-c-blocks wait alassetslibrary

我有一个数组,其中包含与assetslibrary中的图像对应的图像,我需要在执行某项任务之前获取所有这些图像。这是最好的方法吗?我应该使用NSNotificationCenter还是更好地使用块,如果有,可以使用任何示例吗?

这是我的代码:

- (IBAction)buttonClicked:(id)sender {

    NSMutableArray* images = [NSMutableArray array];
    //Need to loop through the takenImagesURLArray
    for (NSURL *imageURL in takenImagesURLArray) {
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:imageURL
                 resultBlock:^(ALAsset *asset) {
                     if (asset) {
                         NSLog(@"HAS ASSET: %@", asset);
                         UIImage *image = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
                         [images addObject:image];
                     } else {
                         NSLog(@"Something went wrong");
                     }
                 }
                failureBlock:^(NSError *error) {
                    NSLog(@"Something went wrong, %@", error);
                }];
    }
    //This will of course be called before images is ready
    [self doCertainTaskWith: images];
}

4 个答案:

答案 0 :(得分:3)

你可以使用Grand Central Dispatch。

但首先,将ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];移到for循环之外,因为它可以重复使用。

现在是真正的代码。它看起来像这样:

dispatch_group_t dgroup = dispatch_group_create(); //0

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

for (NSURL *imageURL in urls) {

    dispatch_group_enter(dgroup); // 1

        [library assetForURL:imageURL resultBlock:^(ALAsset *asset) {
            if (asset) {
                NSLog(@"HAS ASSET: %@", asset);
                UIImage *image = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
                [images addObject:image];

                dispatch_group_leave(dgroup); //2

            } else {
                NSLog(@"Something went wrong");
                dispatch_group_leave(dgroup);
            }
        } failureBlock:^(NSError *error) {
            NSLog(@"Something went wrong, %@", error);
            dispatch_group_leave(dgroup);
    }];

}

dispatch_group_notify(dgroup, dispatch_get_main_queue(), ^{ //3

    NSLog(@"Do something with %d images", [images count]);

});

代码说明(遵循代码中的注释)

  1. 我们创建了一个团队,帮助我们实现我们想要的目标。把它想象成一个简单的清单。

  2. 我们将每个项目输入到组中。可以把它想象为增加对象的retain道具,在本例中是我们的群组。

  3. 当我们完成后,我们告诉它离开小组。可以将其视为在对象上调用release

  4. 当小组上的计数回到0时,所有任务都已完成。无论您需要对图像做什么,都可以在这里完成。

答案 1 :(得分:0)

使用一个简单的计数器,在块外创建并在块内更新(成功和失败)。当计数器值与您知道的图像计数匹配时,执行最终语句(应该在资产库结果块内的if语句内)。

答案 2 :(得分:0)

您概述的阻止方法可能会在获取所有内容之前调用它们。 您可以调用在块操作完成后执行的完成处理程序中处理它们。

我自己也承认与僵局混淆。 我使用this来帮助。

简而言之,我重新安排你所做的将循环置于块中。这里有一些语法上可怕的代码来说明......

- (void)processImagesWithCompletionHandler:void (^)(NSArray*))completion {
    dispatch_async(dispatch_get_global_queue, ^{ //runs in background thread
       **for loop that gets images and adds to an array called images**
       dispatch_async(dispatch_get_main_queue, ^{ //runs on main queue as it may affect the UI
          completion(images);
       });
    });
}

然后你可以用:

来调用它
[self processImagesWithCompletionHandler:^void (NSArray *images) {
   self doCertainTaskWith:images];
}];

答案 3 :(得分:0)

Wain在代码中回答

- (IBAction)buttonClicked:(id)sender {
    __block NSInteger assetCount = 0;
    NSMutableArray* images = [NSMutableArray array];
    //Need to loop through the takenImagesURLArray
    for (NSURL *imageURL in takenImagesURLArray) {
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:imageURL
                 resultBlock:^(ALAsset *asset) {
                     if (asset) {
                          NSLog(@"HAS ASSET: %@", asset);
                        UIImage *image = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
                         [images addObject:image];
                     } else {
                         NSLog(@"Something went wrong");
                     }
                     assetCount++;
                     if (assetCount == takenImagesURLArray.count)
                     {
                         [self doCertainTaskWith:images];
                     }
                 }
                failureBlock:^(NSError *error) {
                    NSLog(@"Something went wrong, %@", error);
                }];
        }
    }