如何使用AFNetworking从一系列URL下载和存储图像?

时间:2013-11-18 17:27:50

标签: ios iphone uiimageview uiimage afnetworking

我正在使用"UIImageView+AFNetworking.h",我的目标是获取名为imageURLArray的NSArray网址,下载所有图片,将其放入带页面控件的滚动视图中。

为此,我在下面的循环中一次下载一张图片,并且先前已分配/初始化的可变数组downloadImageArray,其中存储了下载的图片:

for (int i = 0; i < [imageURLArray count]; i++){
        NSURL *testURL = [imageURLArray objectAtIndex:i];
        NSURLRequest *testURLRequest = [[NSURLRequest alloc] initWithURL:testURL];
        [placeHolderImageView setImageWithURLRequest:testURLRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
            NSLog(@"success");
            NSLog(@"The image is %@", image);
            [downloadedImageArray addObject:image]; //! the exception is thrown here - it says the object is NULL
        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
            NSLog(@"failed to download");
        }];
    }
NSLog(@"Count of images is %i", [downloadedImageArray count]) //this always returns "0"

作为我将对象添加到downloadedImageArray的行中的注释,我得到了添加到可变数组的对象为NULL的异常。我怀疑这是因为在下一个URL到位之前图像还没有完成下载,并且要求再次下载。此外,在循环之后,当我得到downloadedImageArray的计数时,计数返回0.

我的问题是:

  1. 在循环到下一个下载下一张图片的请求之前,如何确保一张图片已完成下载?
  2. 作为一种设计选择,在将所有图像添加到我的滚动视图(每个图像的宽度设置为固定)之前首先下载所有图像是否有意义,或者在滚动到它们时将其下载更有意义?如果是这样,我该如何实现呢?大部分时间imageURLArray的网址数不超过4个。
  3. 谢谢!

3 个答案:

答案 0 :(得分:3)

如果您使用的是最新版本的AFNetworking,要下载图像,您可以执行以下操作:

NSURLRequest* request = [...]
AFHTTPRequestOperation* op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFImageResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation* operation, id responseObject){...} failure:^(AFHTTPRequestOperation* operation, NSError* error) {...}];

[op start];

因此,如果您想循环遍历一系列网址并从每个网址下载图片,那么您就会这样做(并且警告:我还没有对此进行过测试):

NSMutableArray* images = [NSMutableArray arrayWithCapacity:imageURLArray.count];
for(int i = 0; i < imageURLArray.count; i++)
    [images addObject:[NSNull null]];
for(int i = 0; i < imageURLArray.count; i++)
{
    NSURL* url = imageURLArray[i];
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    AFHTTPRequestOperation* op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    op.responseSerializer = [AFImageResponseSerializer serializer];
    [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation* operation, id responseObject){
        UIImage* image = responseObject;
        [images replaceObjectAtIndex:i withObject:image];
    } failure:^(AFHTTPRequestOperation* operation, NSError* error) {...}];

    [op start];
}

NSNull填充图像数组,因为不同索引的图像可能会在不同时间加载,如果索引3处的图像在索引2处的图像之前加载,则会出现超出范围的异常如果你试图将它插入适当的索引。

当这些操作完成后,images数组中的每个图像都将对应imageURLArray中相同索引处的URL。

话虽如此,大多数时候最好只在需要时下载所需的图像。因此,我将使您的视图控制器成为图像滚动视图的委托,然后在滚动时,找出出现了UIImageView个,并在它们上面调用setImageWithURL。但是,如果这太难了,你没有一个非常大的图像,那么上面应该没问题。

答案 1 :(得分:1)

答。 1我们可以使用NSRunLoop等待进程完成试试这个

for (int i = 0; i < [imageURLArray count]; i++)
{
NSURL *testURL = [imageURLArray objectAtIndex:i];
NSURLRequest *testURLRequest = [[NSURLRequest alloc] initWithURL:testURL];
[placeHolderImageView setImageWithURLRequest:testURLRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
    NSLog(@"success");
    NSLog(@"The image is %@", image);

    while (!image)
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

    [downloadedImageArray addObject:image]; //! the exception is thrown here - it says the object is NULL
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
    NSLog(@"failed to download");
}];
}
NSLog(@"Count of images is %i", [downloadedImageArray count]);

现在,在未下载图像之前,图像不会添加到数组中。

答。 2按照此过程显示图像

一个。下载图片

湾添加到数组

℃。添加到滚动条

执行此操作,直到不下载所有图像。

答案 2 :(得分:0)

  1. 如果你没有用__block声明的downloadedImageArray那么它将不会从你的placeHolderImageView setImageWithURLRequest块中写入;

  2. 考虑使用表格视图而不是滚动视图,这样只有在向用户显示单元格时才会发生下载,并且还会考虑先下载缩略图,然后再考虑整个图像;