UICollectionView – 下载图像并有效地重新加载数据,比如Instagram

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

我想复制这个function,但我不知道如何去做。

我目前正在下载一个大的JSON对象,我转换成一个NSDictionaries数组。 每个NSDictionary包含有关每张照片的信息,并且在这些信息当中显示一个URL。 在这个URL,我可以find我需要下载并显示在我的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]){ // 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]; } 

所以基本上,我想知道如何实现Instagram和类似应用程序在显示图片Feed时的function。 另外,我想知道为每个单元启动下载的一个好方法,当下载完成时,更新该单元,而不是使用[reloadData]重绘整个视图,

谢谢

你想要实现的技术叫做延迟加载。 由于您正在使用AFNetworking所以在您的情况下实现这一点会更容易。 您的每个collections视图单元格都需要有一个UIImageView来显示图像。 使用UIImageView+AFNetworking.h类别并通过调用方法设置正确的图像URL

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // .... [cell.imageView setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; // ... return cell; } 

占位符是在下载所需图像之前将显示的图像。 这只会为你做所需的工作。

注意 :默认情况下,URL请求的caching策略为NSURLCacheStorageAllowed ,超时间隔为30秒,并且设置为不处理cookie。 要以不同方式configurationURL请求,请使用setImageWithURLRequest:placeholderImage:success:failure:

另外,为了您的参考,如果您想自己实现延迟加载图像,请遵循此Apple示例代码 。 这是为UITableView但同样的技术也可以用于UICollectionView

希望有所帮助!

使用

[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];

代替

[self.collectionView reloadData];

这里indexPath是相应的UICollectionViewCell对象的NSIndexPath对象

使用以下在cellForItemAtIndexPath委托方法的单元格中加载图像asynchronous

 let url = URL(string: productModel.productImage) let data = try? Data(contentsOf: url!) DispatchQueue.main.async(execute: { collectionViewCell.imageView.image = UIImage(data: data!) }); 

在你的ViewController中实现协议“UICollectionViewDataSourcePrefetching”

类ViewController:UIViewController,UICollectionViewDataSourcePrefetching {

将以下代表设置为情节提要中的collections视图(请参阅附加图像)或以编程方式

ViewController的 viewDidLoad方法

 collectionView.delegate = self collectionView.dataSource = self collectionView.prefetchDataSource = self