我有一个数组,其中包含与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];
}
答案 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]);
});
代码说明(遵循代码中的注释)
我们创建了一个团队,帮助我们实现我们想要的目标。把它想象成一个简单的清单。
我们将每个项目输入到组中。可以把它想象为增加对象的retain
道具,在本例中是我们的群组。
当我们完成后,我们告诉它离开小组。可以将其视为在对象上调用release
。
当小组上的计数回到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);
}];
}
}