[英]ALAssetsLibrary, wait until assetForURL is finished
我有一个带有图像的数组,它与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];
}
你可以使用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]);
});
代码说明(遵循代码中的注释)
我们创建了一个团队,帮助我们实现我们想要的目标。 把它想象成一个简单的列表。
我们将每个项目输入到组中。 可以把它想象为增加对象的retain
支柱,在这种情况下,我们的组。
当我们完成后,我们告诉它离开小组。 将其视为在对象上调用release
。
当计数在组上回到0时,所有任务都已完成。 无论您需要对图像做什么,都可以在这里完成。
使用一个简单的计数器,在块外创建并在块内更新(成功和失败)。 当计数器值与您知道的图像计数匹配时,执行最终语句(应该在资产库结果块内的if
语句内)。
您概述的阻止方法可能会在获取所有内容之前调用它们。 您可以调用在块操作完成后执行的完成处理程序中处理它们。
我承认自己会遇到障碍。 我用这个来帮忙。
简而言之,我会重新安排你所做的将循环置于块中。 这里有一些语法上可怕的代码来说明......
- (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];
}];
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);
}];
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.