UICollectionView图像加载问题

时间:2014-04-25 11:43:41

标签: ios objective-c ios7 uicollectionview uicollectionviewcell

UICollectionView用于显示图像。它工作正常。

问题是当我滚动UICollectionView时,一些可见的单元格现在是不可见的,当我向后滚动以便它们再次可见时,我看到它们没有正确显示。

所以会发生imageA位于索引0而imageB位于索引1.现在滚动并返回原始滚动位置时再次加载这些单元格时,它们的位置要么切换,要么两个细胞都有相同的图像。

最初:

enter image description here

重新加载单元格后

enter image description here

代码:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
                                                                          forIndexPath:indexPath];

    DLog(@"url at index %d : %@", indexPath.row, ((MyObject *)[self.list.array objectAtIndex:indexPath.row]).imageUrl);

    MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.row];

    // Get image in separate thread
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Get image to display
        UIImage * tempImage = object.image;

        if (tempImage)
        {
            // Run code to set image to UIImageView in main thread only.
            dispatch_async(dispatch_get_main_queue(), ^{

                cell.imageView.image = tempImage;
            });
        }
        else
        {
            // Download failed.
            DLog(@"Downloaded image is nil.");
        }
    });

    return cell;
}

我记录了图片网址的值,并记录了正确的值。

3 个答案:

答案 0 :(得分:5)

我也使用了这个技巧,但是线程和线程之间的索引弄得一团糟,所以我搜索了一下,我在GitHub上找到了一个很棒的库。

您只需要#import <SDWebImage/UIImageView+WebCache.h>到项目中,并且只需使用以下代码即可在下载图像时定义占位符:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
                                                             forIndexPath:indexPath];

    DLog(@"url at index %d : %@", indexPath.row, ((MyObject *)[self.list.array objectAtIndex:indexPath.row]).imageUrl);

    MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.row];

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    return cell;
}

它还可以缓存下载的图像并为您提供出色的性能。

希望它会对你有所帮助!

答案 1 :(得分:1)

为什么你想知道一段时间后他们会转到他们的位置?你打电话

cell.imageView.image = tempImage;

异步。这意味着执行不会在图像更改时等待,并使用旧图像显示出列单元格。

答案 2 :(得分:1)

这里有几个问题,但主要是你看到的问题是因为单元格引用不再指向同一个Cell。作为一项学习练习,保留您的代码(或至少是代码的总体布局),您可以通过indexPath获取对您希望项目应用的单元格的引用来解决问题,如果它是仍在显示,分配图像。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell"
                                                                      forIndexPath:indexPath];

    DLog(@"url at index %d : %@", indexPath.item, ((MyObject *)[self.list.array  objectAtIndex:indexPath.item]).imageUrl);

    MyObject *object = (MyObject *)[self.list.array objectAtIndex:indexPath.item];

    // get a weak reference to collectionViewController (assume your code is in a UICollectionViewCcontroller)

    __weak MyCollectionViewController *weakSelf = self; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

     // Get image to display
      UIImage * tempImage = object.image;

     // check if the cell is still visible
     if ([weakSelf.collectionView.indexPathsForVisibleItems containsObject:indexPath]) {

          if (tempImage)
          {
            // Run code to set image to UIImageView in main thread only.
            dispatch_async(dispatch_get_main_queue(), ^{
               // we get a reference to the cell via it's indexPath
                MyCell *cell = (MyCell *)[weakSelf.collectionView cellForItemAtIndexPath:indexPath];
                cell.imageView.image = tempImage;
            });
         }
         else
        {
          // Download failed.
          DLog(@"Downloaded image is nil.");
        }
     }
    });

  return cell;
}

正如Erid建议的那样,使用像SDWebImage这样的东西并将图像url存储在MyObject类中并使用SDWebimage的setImageWithURL设置cell.imageView.image肯定会更好(我个人会写出图像对象类中的检索和图像引用。)

哦,还有一点,您应该将indexPath.section和indexPath.item用于UICollectionViews,将indexPath.row用于UITableView.s