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

时间:2014-09-05 19:08:38

标签: ios uicollectionview sdwebimage

我正在使用UICollectionView来显示一组图像。图像从网络加载。我从在线JSON文件中获取图像URL。图像大小不同,我使用flowlayout将图像放在一起。这里的挑战是,在加载图像之前,您不会知道图像的确切大小。我使用SDWebImage下载和缓存图像。我使用布尔值来检查加载了哪些图像。加载每个图像后,我告诉集合视图在其相应的索引路径上重新加载图像。现在的问题是图像确实正确加载但是当我滚动收集视图时,细胞都搞砸了。这是一些代码:

这是我计算每个细胞大小的地方:

- (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 个答案:

答案 0 :(得分:0)

只要屏幕滚动,

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变量。