Swift:集合视图的懒惰人口

时间:2015-02-28 19:46:18

标签: ios swift uiimageview uicollectionview lazy-loading

我正在学习Swift,并编写一个小应用程序,显示带有图像的集合视图。它不工作,图像永远不会显示。我在collectionView cellForItemAtIndexPath中看到了奇怪的行为:当我懒洋洋地加载要在单元格中显示的图像并第二次调用collectionView.dequeueReusableCellWithReuseIdentifier()时,它会返回一个不同的单元格。这在我滚动集合视图之前发生,因此单元格重用不应该成为问题。这是我的代码:

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

        let reuseIdentifier = "CollectionCell"
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath:indexPath) as! ImageCollectionCell

        cell.imageView.contentMode = UIViewContentMode.ScaleAspectFill

        cell.countLabel.text = "\(indexPath.row+1)"

        let imageIndex = XKCDClient.sharedInstance.totalCount - indexPath.row - 1
        println("loading image # \(imageIndex)")
        XKCDClient.sharedInstance.loadComic(imageIndex, completion: { (comicData) -> Void in

            if let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath:indexPath) as? ImageCollectionCell {
                println("got image # \(imageIndex)")
                cell.imageView.backgroundColor = UIColor.blackColor()
                if(comicData.image != nil) {
//                    cell.imageView.image = comicData.image // (1)

                    cell.imageView.image = UIImage(named: "placeholder") // (2)
                    cell.setNeedsDisplay()
                }
            }
            else {
                println("cell \(imageIndex) already reused");
            }
        })

        return cell
    }

会发生什么:

  • 为每个索引路径调用回调块
  • UIImage对象正确传递到回调块
  • 回调中的单元格没有任何变化似乎有任何影响(包括设置背景颜色)
  • 回调中collectionView.dequeueReusableCellWithReuseIdentifier()返回的单元格与方法开头返回的单元格不同。这似乎是问题的根源。

有人能解释一下这里发生了什么吗?

1 个答案:

答案 0 :(得分:4)

不要在回调闭包中再次调用dequeuReusableCellWithReuseIdentifier,而是调用cellForItemAtIndexPath。注意:在单元格中设置图像时,必须在主线程中执行此操作:

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

    let reuseIdentifier = "CollectionCell"
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! ImageCollectionCell
    cell.imageView.image = nil
    cell.imageView.contentMode = UIViewContentMode.ScaleAspectFill
    cell.countLabel.text = "\(indexPath.row+1)"
    let imageIndex = XKCDClient.sharedInstance.totalCount - indexPath.row - 1
    XKCDClient.sharedInstance.loadComic(imageIndex, completion: { (comicData) -> Void in
         if let img = comicData.image {
             // Note: Set image in the main thread
             dispatch_async(dispatch_get_main_queue()) {
                  cell.imageView.image = img
             }
         } else {
            println("No image in comicData")
            dispatch_async(dispatch_get_main_queue()) {
                  cell.imageView.image = nil
             }
         }
    })

    return cell
}