我弄得一团糟,试图找到一种熟练的方法来解决这个问题,但是却陷入困境。我现在的问题是,我要在执行代码之前先执行代码,这与我的代码块有关。
以下代码的问题在于,在添加postToForm
my之前,该方法已被调用并执行convertedImages
。我该如何解决这个问题,以等待它发生?还是我会以完全错误的方式来解决这个问题?(我也需要了解内存使用情况,需要在发布信息后释放内存。)
这是包含问题的代码:
// create serial queue
dispatch_queue_t queue = dispatch_queue_create("myQueue", 0);
// create dispatch group
dispatch_group_t group = dispatch_group_create();
for(id photos in photoUrls) {
NSString *urlString = photos;
// enqueue operation in queue
dispatch_async(queue, ^{
// enter the group
dispatch_group_enter(group);
// do something async, I do use another dispatch_queue for example
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// wrap in autoreleasepool to release memory upon completion
@autoreleasepool {
// here for example the nested operation sleeps for two seconds
NSURL *url = [NSURL URLWithString:urlString];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:url resultBlock:^(ALAsset *asset) {
//TODO: Deal with JPG or PNG
NSData *imageData = UIImageJPEGRepresentation([self thumbnailForAsset:asset maxPixelSize:1000], 0);
NSString *base64 = [imageData base64EncodedString];
NSLog(@"base64::%@",base64);
[convertedImages addObject:base64];
} failureBlock:^(NSError *error) {
NSLog(@"that didn't work %@", error);
}];
dispatch_group_leave(group);
}
});
// wait until the nested async operation leaves the group (e.g finishes its job)
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"Finished single operation.");
});
}
// will be called once all operations complete
dispatch_async(queue, ^{
NSLog(@"Finished all jobs. ");
NSLog(@"how many::%lu",(unsigned long)convertedImages.count);
[jsonWithPhotos setObject:convertedImages forKey:@"photo64"];
[self postToForm];
});
在加载所有图像之前调用完成块的原因是调用dispatch_group_leave(group);
位置错误。您应该在ALAssetsLibrary的结果块(和错误块)中调用它。其余的是正确的(事实上,正如苹果公司建议实现队列的完成块一样:由于GCD的专用队列是串行的,因此完成块仅是队列本身的最后一块)。
编辑:按要求:事实是ALAssetsLibrary需要一些时间来提取请求的url处的数据(实际上有一个完成块,暗示该操作是异步的)。因此,在为当前网址请求图片后,您立即释放了由创建的信号量,dispatch_group_enter
并且可能在ALAssetsLibrary执行完完成代码块之前发生了。
现在,请记住,如何实现队列的完成块仅对串行队列有效,从iOS 5+开始,您可以通过指定DISPATCH_QUEUE_CONCURRENT
as队列类型来创建并发队列(与全局队列相同),这种方法不再有效。如果在这种情况下您没有并发队列,那么我将检查当前URL是否是ALAssetsLibrary结果块中的最后一个,并在其中调用完成块。
为了完整起见,您可以使用dispatch_semaphore_t
来处理这种情况,从逻辑上讲,它比使用组等待(这里的组由1个运算组成)更正确,但是,我再说一遍,从逻辑上讲,结果更好。
我写的所有内容都写在Apple的并发编程指南中
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句