如何使用AFNetworking按顺序下载图像?按“按顺序”,我还意味着按顺序执行success
块。
最初我认为使用NSOperationQueue
并将每个AFImageRequestOperation
设置为下一个的依赖关系就足够了。像这样:
- (void) downloadImages
{
{ // Reset
[_downloadQueue cancelAllOperations];
_downloadQueue = [[NSOperationQueue alloc] init];
_images = [NSMutableArray array];
}
AFImageRequestOperation *previousOperation = nil;
for (NSInteger i = 0; i < _imageURLs.count; i++) {
NSURL *URL = [_imageURLs objectAtIndex:i];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFImageRequestOperation *operation = [AFImageRequestOperation
imageRequestOperationWithRequest:request
imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[_images addObject:image];
NSLog(@"%d", i);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {}];
if (previousOperation) {
[operation addDependency:previousOperation];
}
previousOperation = operation;
[_downloadQueue addOperation:operation];
}
}
下载图像时按顺序打印i
。但是,当请求已被缓存时,成功块将不按顺序处理。我怀疑这是NSOperation
限制,而不是AFNetworking。
我错过了什么吗?
答案 0 :(得分:0)
作为一种解决方法,我将图像存储在字典中,并在每次请求成功时按顺序处理它们。像这样:
- (void) downloadImages
{
{ // Reset
[_downloadQueue cancelAllOperations];
_downloadQueue = [[NSOperationQueue alloc] init];
_images = [NSMutableArray array];
_imageDictionary = [NSMutableDictionary dictionary];
}
AFImageRequestOperation *previousOperation = nil;
for (NSInteger i = 0; i < _imageURLs.count; i++) {
NSURL *URL = [_imageURLs objectAtIndex:i];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFImageRequestOperation *operation = [AFImageRequestOperation
imageRequestOperationWithRequest:request
imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[_imageDictionary setObject:image forKey:@(i)];
[self processImages];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {}];
if (previousOperation) {
[operation addDependency:previousOperation];
}
previousOperation = operation;
[_downloadQueue addOperation:operation];
}
}
- (void) processImages
{
for (NSInteger i = _images.count; i < _imageURLs.count; i++) {
UIImage *image = [_imageDictionary objectForKey:@(i)];
if (!image) break;
[_images addObject:image];
NSLog(@"%d", i);
}
}
这始终按顺序打印i
。
答案 1 :(得分:0)
您的解决方案可以正常工作,这是另一种方法:
对于“完美”的UX,您应该并行发出所有操作,并按顺序处理图像(如果不需要,请不要等待)。
(这里的错误处理方式不同)
你可以尝试这个(未经测试,你可以更好地设计模型[不要只使用这样的数组]):
- (void) processImage:(UIImage*)image
{
//do something with the image or just [_images addObject:image]
}
- (void) downloadImages
{
{ // Reset
[_downloadQueue cancelAllOperations];
_downloadQueue = [[NSOperationQueue alloc] init];
}
__block NSMutableArray* queue = [[NSMutableArray alloc] initWithCapacity:[_imageURLs count]];
for (NSURL* url in _imageURLs) {
__block NSLock* lock = [[NSLock alloc] init];
__block NSMutableArray* container = [NSMutableArray new];
[lock lock];
[queue addObject:@[lock,container,url]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
void(^compBlock)(NSURLRequest *request,
NSHTTPURLResponse *response,
UIImage *image) = ^(NSURLRequest *request,
NSHTTPURLResponse *response,
UIImage *image)
{
[container addObject:image];
[lock unlock];
};
NSOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request
imageProcessingBlock:nil
success:compBlock
failure:compBlock];
[_downloadQueue addOperation:operation];
}
__block __weak id weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (NSArray* arr in queue) {
NSLock* lock = arr[0];
[lock lock];
NSMutableArray* container = arr[1];
if ([container count]) {
[weakSelf processImage:container[0]]; //might want to call this on main thread
} else {
//error on url = arr[2]
}
[lock unlock];
}
});
}