使用AFNetworking按顺序下载图像

时间:2013-04-06 16:11:27

标签: ios afnetworking nsoperation nsoperationqueue

如何使用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。

我错过了什么吗?

2 个答案:

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