从网络加载图像并将其显示在集合视图中

Posted

技术标签:

【中文标题】从网络加载图像并将其显示在集合视图中【英文标题】:Loading images from web and displaying it in a collectionview 【发布时间】:2014-09-05 19:08:37 【问题描述】:

我正在使用 UICollectionView 来显示一组图像。图片是从网上加载的。我从在线 JSON 文件中获取图像 URL。图像大小不同,我使用流程布局将图像放在一起。这里的挑战是,在加载图像之前,您不会知道图像的确切大小。我使用 SDWebImage 下载和缓存图像。我使用一个布尔值来检查加载了哪些图像。加载每个图像后,我告诉 collectionview 在其相应的 indexpath 处重新加载图像。现在的问题是图像确实加载正确但是当我滚动collectionview时单元格都搞砸了。这是一些代码:

这是我计算每个单元格大小的地方:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(NHBalancedFlowLayout *)collectionViewLayout preferredSizeForItemAtIndexPath:(NSIndexPath *)indexPath
   

if (didLoadImage == YES) 
   return [loadedImage size];
   
else
   
    return CGSizeMake(300, 140);
   

这是加载和设置图像的位置:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

GalleryCell *customCell = [collectionView
                           dequeueReusableCellWithReuseIdentifier:@"cell"
                           forIndexPath:indexPath];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[galleryLargeLinks objectAtIndex:indexPath.row]]];

customCell.backgroundColor = [UIColor blackColor];

[customCell.imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:@"placeholder"] success:^(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image)
 
     loadedImage = image;
     didLoadImage = YES;
     [customCell.imageView setImage:image];
     [collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];

  failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
 
     NSLog(@"fail");
     [activityIndicator stopAnimating];
 ];
return customCell;

【问题讨论】:

【参考方案1】:

UICollectionViewCell's 在滚动离开屏幕时会被重复使用。因此,由于您使用的是异步块来加载它们,因此单元格可能会在准备就绪时被分配给另一个 indexPath。如果您愿意,您可以继续使用setImageWithURLRequest:,但是,您应该添加另一个检查以查看 indexPath 在加载时是否仍然是您所期望的。像这样的:

[customCell setIndexPath:indexPath];
__weak GalleryCell *weakCell = cell;
__weak CollectionView *weakCollectionView = collectionView;
[customCell.imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:@"placeholder"] success:^(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image)
 
     if([weakCell.indexpath isEqual:indexPath])
         [weakCell.imageView setImage:image];
         [weakCollectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
     

  failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
 
     [activityIndicator stopAnimating];
 ];

至于collectionView:layout:preferredSizeForItemAtIndexPath:,您需要以完全不同的方式进行检查。一种选择可能是将缓存的图像作为数据源的键,这样您就可以检查数据源数组中的值并查看它是否在缓存中。如果是,则抓取图像,否则返回默认值。写出来的代码太多了,但基本上你应该检查你的数据源/缓存,而不仅仅是两个可以随时更改的随机 BOOLUIImage 变量。

【讨论】:

感谢您的回复。但是我如何将weakcell.indexpath 与indexpath 进行比较呢?没有 setindexpath 方法。 你需要在你的 CustomCell 类上创建一个属性 -> NSIndexPath *indexPath;

以上是关于从网络加载图像并将其显示在集合视图中的主要内容,如果未能解决你的问题,请参考以下文章

从 URL 中获取图像并将其显示在 Collection 视图中,怎么做? [复制]

从文档文件夹加载集合视图中的图像

集合视图未加载图像

图像未显示在集合视图单元格中

将图像从解析加载到集合视图 Swift

当图像保存在核心数据的集合视图中时,应用程序因内存错误而崩溃