按照AFNetworking的顺序下载图像

你如何下载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]; } } 

下载图像时按顺序打印。 但是,当请求已被caching时,成功块将按顺序处理。 我怀疑这是NSOperation限制,而不是AFNetworking。

我错过了什么吗?

作为解决方法,我将图像存储在字典中,并在每次请求成功时按顺序处理它们。 喜欢这个:

 - (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的秩序。

您的解决scheme将正常工作,这是另一种方式来做到这一点:

对于“完美”用户体验,您应该并行执行所有操作,并按顺序处理图像(不要等到没有必要的时候)。
(error handling在这里是不同的)
你可以试试这个(未经testing,你可以更好地devise模型[不要只使用这样的数组]):

 - (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]; } }); }