UICollectionView在滚动时重新加载错误的图像 [英] UICollectionView reloads wrong images on scroll

查看:302
本文介绍了UICollectionView在滚动时重新加载错误的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我从文本文件下载图像URL,将其存储在NSMutableArray中,然后从CellforItemAtIndexPath中的这些URL下载图像。但是,当我向上和向下滚动片刻时,错误的图像位于错误的位置。它纠正了一秒钟,但我想摆脱滚动问题。这是代码:

In the code below, I download image URLs from a text file, store it in a NSMutableArray, then download the images from from those URLS in CellforItemAtIndexPath. However, when I scroll up and down, for a brief moment, the wrong image is in the wrong place. It corrects a second later but I would like to get rid of that scrolling problem. Here's the code:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *identifier = @"Cell2";

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    AsyncImageView *recipeImageView = (AsyncImageView *)[cell viewWithTag:100];
    UILabel *titleView = (UILabel *)[cell viewWithTag:101];
    titleView.numberOfLines = 3;
    UIImageView *overlay = (UIImageView *)[cell viewWithTag:111];
    FXBlurView *blurView = (FXBlurView *)[cell viewWithTag:110];
    blurView.tintColor = [UIColor colorWithRed:51.0 green:51.0 blue:51.0 alpha:1];


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        hi = [self videoTitle];
        images = [self firstPhoto];
        // switch to a background thread and perform your expensive operation


        // switch back to the main thread to update your UI


        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *imgSrc;

            NSString *url = images[indexPath.row];
            imgSrc = url;
            if (imgSrc != nil && [imgSrc length] != 0 ) {
                [recipeImageView setImageWithURL:[NSURL URLWithString:images[indexPath.row]] placeholderImage:[UIImage imageNamed:@"red.png"]];

            }
            else {
                NSLog(@"noimage");
                recipeImageView.image = [UIImage imageNamed:@"red.png"];
            }
            titleView.text = hi[indexPath.row];


        });
    });

    return cell;


    // recipeImageView.image = [UIImage imageNamed:[videoList objectAtIndex:indexPath.row]];

}

有什么想法吗?谢谢。

推荐答案

我注意到一堆没有评论的downvotes,在再次阅读我的答案之后我想原来接受的答案(下面)这条线可能会更好。

I noticed a bunch of downvotes without comments and after reading my answer again I guess the original accepted answer (below the line) could have been better.

这些问题还有一些问题。 UITableView只创建足够的UITableViewCells来显示视图中的每个单元格以及要滚动到视图中的内容。其他单元格在滚出视图后将重新使用。

There are a few things going on with these kinds of problems. The UITableView only creates just enough UITableViewCells to display every cell in view plus what's going to scroll into view. The other cells are going to get re-used after they scroll out of view.

这意味着当您快速滚动时,单元格会多次设置以获取图像异步,然后显示它,因为它获取图像非常慢。加载图像后,它将显示在最初调用它的单元格上,但该单元格可能已经重新使用。

This means when you're scrolling fast the cell gets set up multiple times to fetch an image async and then display it because it's pretty slow fetching the image. After the image loads it will show itself on the cell that originally called to fetch it, but that cell might be re-used already.

现在我有一个bufferedImage:UIImage ?我用作UITableViewCells数据的任何数据类的属性。这最初总是为零,所以我获取图像异步,当dispatch_async返回时,它会将它存储在那里,所以下次我需要显示这个单元格它已经准备就绪,如果它仍然是同一个单元格,我也会在单元格中显示它。

Nowadays I have a bufferedImage: UIImage? property on whatever data class I use as data for the UITableViewCells. This will initially always be nil so I fetch the image async and when the dispatch_async returns it will store it there so the next time I need to show this cell it's ready, and if it's still the same cell I will also display it in the cell.

所以正确的做法是:


  • 开始配置包含数据对象的单元格

  • 将数据对象存储在单元格中以便稍后引用

  • 检查数据对象是否已有图像集在bufferedImage中如果是这样显示它就是它

  • 如果还没有图像,请将当前图像重置为空或占位符并开始在后台下载图像

  • 异步调用返回时将图像存储在bufferedImage属性中

  • 检查当前单元格中存储的对象是否仍然是您为该图像获取的对象( 这非常重要),如果不做的话

  • 如果你仍然在同一个单元格中显示图像
  • Start configuring the cell with your data object
  • Store the data object in your cell so it can be referred later
  • Check if the data object already has an image set in bufferedImage and if so display it and that's it
  • If there's no image yet, reset the current image to nothing or a placeholder and start downloading the image in the background
  • When the async call returns store the image in the bufferedImage property
  • Check if the object that is stored in the current cell is still the same object you fetched the image for (this is very important), if not don't do anything
  • If you're still in the same cell display the image

所以你在异步调用中传递了一个对象,所以你可以存储提取的图像。还有另一个对象可以在当前单元格中进行比较。在获得图像之前,细胞通常已经被重复使用,因此在下载图像时这些对象会有所不同。

So there's one object you pass along in your async call so you can store the fetched image. There's another object that's in the current cell that you can compare to. Often the cell already got reused before you got the image, so those objects are different by the time your image is downloaded.

滚动和旋转CollectionViews总是有点问题。我总是有同样的问题,图像出现在错误的单元格中。对于集合视图,会进行某种优化,这会影响图像,但不会影响标签。对我来说这是一个错误但在三个iOS版本之后仍然无法解决。

Scrolling and rotating CollectionViews always has been a bit problematic. I always have the same problem, images that appear in the wrong cells. There is some kind of optimization going on for the collectionview that affects images but not labels. To me it's a bug but it still isn't solved after three iOS releases.

您需要实现以下内容:

https://developer.apple.com/library/ios/documentation/uikit/reference/UICollectionViewLayout_class/Reference/Reference.html#//apple_ref/occ/instm/UICollectionViewLayout/shouldInvalidateLayoutForBoundsChange

这应该总是返回YES基本上总是刷新它。如果这可以解决您的问题,那么您可以考虑不是每次都执行整个重绘,因为它对性能有害。我个人花了很多时间来计算一个屏幕已经通过或线路已经过去等等但是它变得很吵,所以我最后只回到YES。 YMMV。

This should always return YES basically to always refresh it. If this solves your problem then you could look into not executing the whole redraw every time as it's bad for performance. I personally spent a lot of time in counting if a screen had passed or line had passed and so on but it became stuttery instead so I ended up just returning YES. YMMV.

这篇关于UICollectionView在滚动时重新加载错误的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆