当我向下滚动并返回时,我的数据在 UITableViewCell 中发生变化

My data changes in UITableViewCell when I scroll down and get back

当我在我的 tableView 控制器中填充新数据时,我的顶部单元格正在被底部单元格重写。 让我解释。我有一张图像在底部的最新单元格行中异步加载。所有其他单元格都在静态加载应用程序中的图像。当我向下滚动我的应用程序并显示我的底部单元格,该单元格的图像与其他单元格不同,然后再次向上滚动时,我看到第一个商店图像已更改为底部单元格中加载的动态图像。有谁知道为什么会这样?

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

    let cell : shopsTableViewCell = tableView.dequeueReusableCellWithIdentifier("shopCell", forIndexPath: indexPath) as! shopsTableViewCell

    cell.index = indexPath.row
    let qualityOfServiceClass = QOS_CLASS_BACKGROUND
    let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
    let apiCall = webApi()


        dispatch_async(backgroundQueue, {
            apiCall.downloadPhotoAsync("http://api-ytyg.wbbdev.com/files/shops/\(shops[indexPath.row].id)/\(shops[indexPath.row].featured_img)"){(image: UIImage?) -> Void in
                dispatch_async(dispatch_get_main_queue()){
                    if(image != nil){
                        if (cell.index == indexPath.row){
    //                            shops[indexPath.row].photo = image!
                            cell.shopImg?.image = image
                        }

                    }else{
                        shops[indexPath.row].photo = UIImage.init(named: "No_Image_Available.jpg")!
                    }
                }
            }
        })
    cell.shopName?.text = shops[indexPath.row].name
    cell.shopDescription?.text = shops[indexPath.row].address

    cell.label1?.text = shops[indexPath.row].city + " | " + shops[indexPath.row].distance + "Km"
    cell.becomeFirstResponder()
    return cell
}

我认为问题在于当您滚动时,您的图像仍在下载过程中(这就是为什么您在该特定代码行上有一个 nil 的原因)。所以你必须等待它。

我猜你有一组图像。如果你不这样做,那么你必须做一个。你必须像这样使用它:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return arrayThatcontainsShopImages.count
}

注意:每次将下载的图像添加到此数组时,都应调用 tableView.reloadData()

使用 SDWebImage 可能要好得多。看看下面使用这个库的代码,你只是创建了一个 UIImageView 的实例。然后使用这个库,你可以直接下载图片到imageview实例,访问图片,你可以使用imageView.image 属性 of UIImageView class

 let imageView = UIImageView()
 imageView.sd_setImageWithURL(someURL, placeholderImage: UIImage())
 self.arrayOfImageViews.append(imageView)

这是因为你的细胞被重复使用了:

// this line initialize a cell of type shopsTableViewCell 
//if no cell can be reused, get an already used cell else
let cell : shopsTableViewCell 
                 = tableView.dequeueReusableCellWithIdentifier("shopCell",
                                  forIndexPath: indexPath) as! shopsTableViewCell

所以图像和其他数据应该是出列单元格的最后一个图像和数据。

为避免这种情况,您应在单元格 class 文件中实施 prepareForReuse 以重置数据和图像。 docs of apple about prepareForReuse func

来自 Apple 文档:

If a UITableViewCell object is reusable—that is, it has a reuse identifier—this method is invoked just before the object is returned from the UITableView method dequeueReusableCellWithIdentifier:. For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. If the cell object does not have an associated reuse identifier, this method is not called. If you override this method, you must be sure to invoke the superclass implementation.

 //Example :
 override func prepareForReuse() {
    super.prepareForReuse()
    //Do reset here
    this.shopImg?.image = nil
    this.shopName?.text = ""
    this.shopDescription?.text = ""

}