0

如何使用 AFNetworking 按顺序下载图像?通过“按顺序”,我还指success按顺序执行块。

NSOperationQueue最初我认为使用 a并将每个设置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。

我错过了什么吗?

4

2 回答 2

0

您的解决方案可以正常工作,这是另一种方法:

对于“完美”的用户体验,您应该并行发出所有操作并按顺序处理图像(如果不需要,请不要等待)。
(这里的错误处理方式不同)
你可以试试这个(未经测试,你可以更好地设计模型[不要只使用这样的数组]):

- (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];
        }
    });    
}
于 2013-04-06T18:43:14.940 回答
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

于 2013-04-06T16:21:21.097 回答