重复使用的单元格在刷新图像时滞后

Posted

技术标签:

【中文标题】重复使用的单元格在刷新图像时滞后【英文标题】:Reused cell is lagging in refreshing image 【发布时间】:2015-03-31 20:01:27 【问题描述】:

这里的主要问题是我正在将图像加载到自定义单元格中,并且在滚动时,重用的单元格在加载新图像时会显示旧图像。

坦率地说,不会有很多单元格,所以我的第一个想法是我可以使用 tableView.dequeueReusableCellWithIdentifier 来解决问题,但是我想尝试解决的每个地方都有人质疑为什么有人会这样做,或者他们只是提供模糊的建议而没有任何例子。

在重新处理图像时没有这种滞后的情况下显示单元格的最佳方式是什么?

class FavoritesPropertyViewCell: UITableViewCell 
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
    @IBOutlet weak var cellPropertyImage: UIImageView!
    @IBOutlet weak var cellRoomsValue: UILabel!
    @IBOutlet weak var cellSpaceValue: UILabel!
    @IBOutlet weak var cellPriceRangeValue: UILabel!
    @IBOutlet weak var cellCityStateZipValue: UILabel!
    @IBOutlet weak var cellAddressValue: UILabel!



 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell         


            var newPropertyCell: FavoritesPropertyViewCell = tableView.dequeueReusableCellWithIdentifier("FavoritesPropertyCell", forIndexPath: indexPath) as FavoritesPropertyViewCell

//... Get image, format values ...


                // Put everything in the labels.
                newPropertyCell.cellRoomsValue.text = roomsValue
                newPropertyCell.cellSpaceValue.text = spaceValue
                newPropertyCell.cellPriceRangeValue.text = priceValue
                newPropertyCell.cellAddressValue.text = addressValue
                newPropertyCell.cellCityStateZipValue.text = cityStateZipValue

                return newPropertyCell

    

【问题讨论】:

如何在不使用 tableView.dequeueReusableCellWithIdentifier 的情况下使用它? 【参考方案1】:

使用标准 UIImageView 无法解决滚动速度与网络加载速度的问题。

我的经验表明,绝对需要使用图像缓存。 有一些 cocoapods 实现了图像缓存,你可以查看 AsyncImageView 或NPRImageView

【讨论】:

我最终合并了一个图像缓存,这产生了巨大的影响。再次感谢。【参考方案2】:

您应该使用占位符图像并将图像设置为初始化和重用单元格时的图像,在您的 MyCell.m 中放置类似的内容:

- (void)awakeFromNib 

    [super awakeFromNib];

    UIImage *placeHolder = [UIImage imageNamed:@"profilePlaceholder"];
    self.propertyImage=placeholder;



-(void)prepareForReuse 

    //this is called each time we reuse a cell
    UIImage *placeHolder = [UIImage imageNamed:@"profilePlaceHolder"];
    self,propertyImage=placeHolder;


现在您还想做的是创建一个图像缓存,这可以只是一个 NSMutableDictionary,然后在您的单元创建中执行以下操作:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    UIImage *cachedImage = self.images[cell.propertyName];
            if (cachedImage) 
                //use cached image
                cell.propertyImage=cachedImage;
            

            else 

                 //your image download code here



                 //then add the image to the dictionary
                 [self.images setObject:downloadedImage forKey:cell.popertyName];

                //and set it
                cell.propertyImage = downloadedImage;

无论如何,这些都是基础。

如果您不想使用出队,那么只需将单元格创建更改为:

MyCell *cell = [[MyCell init] alloc]; 

或者无论如何你初始化你的单元格...

【讨论】:

不使用 tableView.dequeueReusableCellWithIdentifier 怎么办? 你为什么不想使用出队呢?它只会让您的餐桌更有效率并且易于设置。 你真的应该使用它。您所要做的就是在界面构建器中设置标识符......实际上并没有任何额外的代码。 我明白了,我真的明白了。但是,我理解为什么,正如我在问题中所展示的那样,使用它意味着当系统重用时,在单元之间切换存在延迟。如果单元重用背后的想法是节省内存,那么它有点违背了创建图像缓存的目的,因为我只是将大部分数据(图像)保存到内存中。我将继续对此进行探索,看看是否可以提前删除图像或重复使用,但由于进入此表格视图的数据有限,我认为不使用它会是一个大问题。 您在应用中发布的图片。它在两个不同的占位符图像之间切换。这两个都存储在本地对吗?如果它是本地的,那么图像变化那么慢应该没有问题【参考方案3】:

如果您从网络加载图像,请在设置新图像之前尝试设置cell.image = nil。它至少会在下一张加载到它的位置时清除图像。

【讨论】:

由于这是一个自定义单元格,因此必须以不同的方式引用图像,我尝试将其设置为 nil,但它让我有点合适。我今天尝试了几种不同的方法,但明天我会重新处理它,看看是否有我错过的东西。谢谢。【参考方案4】:

我找不到一种方法来绕过使用 tableView.dequeueReusableCellWithIdentifier 将单元格放入它自己的 xib 并以这种方式调用它(从长远来看,我可能最终会这样做),以防止看起来是重新加载图像,现在我只是在实例化 newPropertyCell 后立即将图像设置为占位符。

引用不存在的图像不会带回任何东西,这几乎是我想要发生的事情。

注意:“占位符”是对不存在的文件的引用,而不是错误,它不返回任何内容。

var newPropertyCell: FavoritesPropertyViewCell = tableView.dequeueReusableCellWithIdentifier("FavoritesPropertyCell") as FavoritesPropertyViewCell

newPropertyCell.cellPropertyImage.image = UIImage(named: "placeholder") 

稍后我可能会回来缓存图像,以便具有更大的持久性,并且我不必点击 API 来检查图像,或者在滚动时再次下载它。

谢谢大家!

【讨论】:

旁注:将图像设置为“nil”在 swift 中不起作用。

以上是关于重复使用的单元格在刷新图像时滞后的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 的单元格在滚动后并不总是刷新

滚动后的单元格在图像上显示图像

UITableview刷新单元格在部分标题下滚动

图像下载后调整表格单元格大小

表视图单元格在重新加载表视图和滚动时重复内容

UICollectionView 单元格在可见时不断重新加载