UICollectionView - 下载图像和有效重新加载数据,如Instagram [英] UICollectionView - Downloading images and effective reloading of data, like Instagram

查看:165
本文介绍了UICollectionView - 下载图像和有效重新加载数据,如Instagram的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到,像Intagram这样的应用程序使用 UICollectionViews 显示照片源。
我也注意到,这些照片的单元格以某种方式放置在屏幕之前实际的照片完全下载。然后当下载完成时,该照片会在正确的单元格中正常显示。



我想复制该功能,但我不知道该怎么做。



我目前正在下载一个大型的 JSON 对象,我将其转换为 NSDictionaries 数组。每个 NSDictionary 包含有关每张照片的信息,在这些信息中,会显示一个URL。在这个URL,我可以找到我需要下载并显示在我的 UICollectionViewCells



现在,我迭代这个列表,并为我看到的每个URL启动一个下载。下载完成后,我使用 [self.collectionView reloadData] 重新载入collectionview。但是,你可以想象,如果我有30个单元格,都想要一个图像,有很多 reloadData 调用。



我使用AFNetworking来处理下载,这里是我根据前面提到的URL调用的方法:

   - (void)downloadFeedImages:(NSString *)photoURL imageDescs:(NSDictionary *)imageDescs photoId:(NSString *)photoID {
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
NSString * directory = [paths objectAtIndex:0];

NSString * foofile = [directory stringByAppendingPathComponent:photoID];

if([[NSFileManager defaultManager] fileExistsAtPath:foofile]){
//如果图像被缓存
[self.collectionView reloadData];
return;
}

NSLog(@photoURL:%@,photoURL);
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:photoURL]];
AFImageRequestOperation * operation = [AFImageRequestOperation imageRequestOperationWithRequest:request
imageProcessingBlock:nil
success:^(NSURLRequest * request,NSHTTPURLResponse * response,UIImage * image){
// Save Image
NSLog(@URL-RESPONSE:%@,image);
NSString * myFile = [directory stringByAppendingPathComponent:photoID];

NSData * imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:myFile atomically:YES];
[self.collectionView reloadData];
}
失败:^(NSURLRequest * request,NSHTTPURLResponse * response,NSError * error){
NSLog(@ERROR:%@,[error localizedDescription]);
}];
[[WebAPI sharedInstance] enqueueHTTPRequestOperation:operation];
}

所以基本上,我想知道如何实现Instagram和类似应用程序在显示带有图像的Feed时所具有的功能。
此外,我想知道一个好的方法来启动每个单元格的下载,当下载完成,更新该单元格,不使用 [reloadData] 重绘整个视图



感谢

解决方案

加载。因为你使用 AFNetworking ,在你的情况下将更容易实现这一点。每个集合视图单元格需要有一个 UIImageView 才能显示图像。使用 UIImageView + AFNetworking.h 类别,并通过调用方法设置正确的图片网址

   - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{
// ...

[cell.imageView setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@placeholder.png]];

// ...
return cell;
}

占位符是在下载所需图片之前显示的图片。

:默认情况下,URL请求的缓存策略为 NSURLCacheStorageAllowed ,超时间隔为30秒,并且设置为不处理cookie。要不同地配置URL请求,请使用 setImageWithURLRequest:placeholderImage:success:failure:



如果您想自己实现延迟加载图片,请按照此 Apple示例代码 。这是 UITableView ,但是同样的技术也可以用于 UICollectionView



希望有帮助!


I noticed that apps like Intagram uses UICollectionViews to display the feed of photos. I also noticed that the cells for these photos is somehow placed on screen before the actual photos are downloaded completely. Then when a download completes, that photo is nicely displayed in the correct cell.

I would like to copy that functionality, but I do not know how to go about it.

I am currently downloading a large JSON object which I transform to an array of NSDictionaries. Each NSDictionary contains information about each photo, and among that information, an URL is presented. At this URL, I can find the corresponding image that I need to download and display in my UICollectionViewCells

As for now, I iterate this list and initiate a download for each URL I see. When that download is complete, I reload the collectionview using [self.collectionView reloadData]. But, as you can imagine, if I have 30 cells that all wants an image, there is a lot of reloadData calls.

I am using AFNetworking to handle the download, here is the method, which I call based on the URL I mentioned before:

-(void) downloadFeedImages:(NSString *) photoURL imageDescs:(NSDictionary*)imageDescs photoId:(NSString *)photoID{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *directory = [paths objectAtIndex:0];

    NSString* foofile = [directory stringByAppendingPathComponent:photoID];

    if([[NSFileManager defaultManager] fileExistsAtPath:foofile]){
        // IF IMAGE IS CACHED
        [self.collectionView reloadData];
        return;
    }

    NSLog(@"photoURL: %@", photoURL);
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photoURL]];
    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request
                                                                              imageProcessingBlock:nil
                                                                                           success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
                                                                                               // Save Image
                                                                                               NSLog(@"URL-RESPONSE:%@", image);
                                                                                               NSString *myFile = [directory stringByAppendingPathComponent:photoID];

                                                                                               NSData *imageData = UIImagePNGRepresentation(image);
                                                                                               [imageData writeToFile:myFile  atomically: YES];
                                                                                               [self.collectionView reloadData];
                                                                                           }
                                                                                           failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
                                                                                               NSLog(@"ERROR: %@", [error localizedDescription]);
                                                                                           }];
    [[WebAPI sharedInstance] enqueueHTTPRequestOperation:operation];
}

So basically, I wonder how I can achieve the functionality that Instagram and similar applications has when it comes to displaying a feed with images. In addition, I would like to know a good way to initiate a download for each cell, and when that download is finished, update that cell, not redraw the entire view using [reloadData]

Thanks

解决方案

The technique you want to implement is called lazy loading. Since you are using AFNetworking it will be easier to implement this in your case. Each of your collection view cell needs to have a UIImageView to display the image. Use the UIImageView+AFNetworking.h category and set the correct image URL by calling method

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // ....

    [cell.imageView setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    // ...
    return cell;
}

Placeholder is the image which will be displayed until required image is downloaded. This will simply do the required job for you.

Note: By default, URL requests have a cache policy of NSURLCacheStorageAllowed and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use setImageWithURLRequest:placeholderImage:success:failure:.

Also, for you reference, if you want to implement lazy loading of images yourself, follow this Apple sample code. This is for UITableView but same technique can be used for UICollectionView as well.

Hope that helps!

这篇关于UICollectionView - 下载图像和有效重新加载数据,如Instagram的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆