UICollectionView 图片闪烁问题

3

我有一个UICollectionView,显示全屏的单元格(即画廊)。 有时,在向左或向右滑动以获取新图像时,会短暂地显示错误的图像,然后才会更新为正确的图像。 其他情况下,可能会显示错误的图像,但如果您向左滑动再向右滑动(即图像消失并重新出现),则正确的图像会出现。 我不明白这种行为的原因。 当集合视图需要它们时,图像会异步下载。 以下是代码:

 let blank = UIImage(named: "blank.png")
 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
     let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell

    let image = images[indexPath.row]
    if let imageView = cell.viewWithTag(5) as? UIImageView {
        imageView.image = blank
        if let cachedImage = cache.objectForKey(image.url) as? UIImage {
            imageView.image = cachedImage
        } else {
            UIImage.asyncDownloadImageWithUrl(image.url, completionBlock: { (succeded, dimage) -> Void in
                if succeded {
                    self.cache.setObject(dimage!, forKey: image.url)
                    imageView.image = dimage
                } 
            })
        }
    }

    return cell
}

UIImage.asyncDownloadImageWithUrl是什么:

extension UIImage {
   static func asyncDownloadImageWithUrl(url: NSURL, completionBlock: (succeeded: Bool, image: UIImage?) -> Void) {
       let request = NSMutableURLRequest(URL: url)
       NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: { (response, data, error) in
           if error == nil {
               if let image = UIImage(data: data) {
                  completionBlock(succeeded: true, image: image)
               }
           } else {
                  completionBlock(succeeded: false, image: nil)
           }

       })
     }
  }

对于第一张显示的图片:

func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
    if let index = self.index {
        let newIndexPath = NSIndexPath(forItem: index, inSection: 0)
        self.collectionView.scrollToItemAtIndexPath(newIndexPath, atScrollPosition: UICollectionViewScrollPosition.Left, animated: false)
        self.index = nil
    }
}
1个回答

10

这是我认为正在发生的事情:

  • 单元格A出现
  • 请求加载图像A到单元格A
  • 单元格A从屏幕消失
  • 单元格A重新出现(被重用)
  • 请求加载图像B到单元格A
  • 图像A的请求完成
  • 图像A加载到单元格A
  • 图像B的请求完成
  • 图像B加载到单元格A

这是因为您没有追踪哪个图像URL应该在完成块中加载。

尝试这样做:

一种方法是将应该存在的图像的URL存储在您的UICollectionViewCell中。为此,请创建一个子类:

class CustomCollectionViewCell:UICollectionViewCell {
    var urlString = ""
}

那么:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CustomCollectionViewCell

    let image = images[indexPath.row]
    if let imageView = cell.viewWithTag(5) as? UIImageView {
        imageView.image = blank
        cell.urlString = image.url.absoluteString
        if let cachedImage = cache.objectForKey(image.url) as? UIImage {
            imageView.image = cachedImage
        } else {
            UIImage.asyncDownloadImageWithUrl(image.url, completionBlock: { (succeded, dimage) -> Void in
                if succeded {
                    self.cache.setObject(dimage!, forKey: image.url)
                    //
                    // This can happen after the cell has dissapeared and reused!
                    // check that the image.url matches what is supposed to be in the cell at that time !!!
                    //
                    if cell.urlString == image.url.absoluteString {
                        imageView.image = dimage
                    }

                } 
            })
        }
    }

    return cell
}
为了得到更准确的回复,请发布项目(或者其简化版本)。重新创建您的环境并测试需要很多工作。

这似乎有效。我得弄清楚为什么 ^-^ 谢谢 - Phoenix
很高兴听到这个消息!就像我所说的,这一切都与请求可能需要一段时间才能完成有关,在此期间相同的“UICollectionViewCell”可以被“UICollectionView”重用以显示不同的内容。异步网络调用没有执行顺序的保证!你能把答案标记为正确的吗?这样问题就不会显示为“未回答”。 - Juan Carlos Ospina Gonzalez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接