我注意到像Intagram这样的应用使用UICollectionViews
来显示照片的Feed。
我还注意到这些照片的单元格以某种方式放在屏幕上,然后完全下载实际照片。然后,当下载完成时,该照片很好地显示在正确的单元格中。
我想复制该功能,但我不知道如何去做。
我目前正在下载一个大型 JSON 对象,我将其转换为 NSDictionaries 数组。每个NSDictionary
都包含有关每张照片的信息,在这些信息中,会显示一个网址。在此URL,我可以找到我需要下载并显示在UICollectionViewCells
至于现在,我迭代这个列表并为我看到的每个URL启动下载。下载完成后,我使用[self.collectionView reloadData]
重新加载集合视图。但是,正如您可以想象的那样,如果我有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];
}
所以基本上,我想知道如何在显示带图像的Feed时实现Instagram和类似应用程序的功能。 另外,我想知道为每个单元格启动下载的好方法,当下载完成后,更新该单元格,而不是使用 [reloadData] 重新绘制整个视图
由于
答案 0 :(得分:16)
您要实现的技术称为延迟加载。由于您使用的是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 sample code进行操作。这适用于UITableView
,但同样的技术也可以用于UICollectionView
。
希望有所帮助!
答案 1 :(得分:2)
使用
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
而不是
[self.collectionView reloadData];
此处indexPath
是相应NSIndexPath
对象的UICollectionViewCell
对象
答案 2 :(得分:1)
使用以下命令在 cellForItemAtIndexPath 委托方法中的单元格中加载图像异步
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 {
将以下代理设置为storyboard中的集合视图(请参阅附图) 或以编程方式
在 ViewController viewDidLoad 方法
collectionView.delegate = self
collectionView.dataSource = self
collectionView.prefetchDataSource = self