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

时间:2016-06-30 19:46:57

标签: swift uitableview asynchronous swift2 xcode7

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

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
}

enter image description here

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:7)

这是因为您的细胞正在重复使用:

// 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

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

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

来自Apple文档:

  

如果UITableViewCell对象是可重用的 - 也就是说,它具有重用标识符 - 在从UITableView方法dequeueReusableCellWithIdentifier:返回对象之前调用此方法:出于性能原因,您应该仅重置与内容无关的单元格属性,例如,alpha,编辑和选择状态。 tableView中的表视图委托:cellForRowAtIndexPath:在重用单元格时应始终重置所有内容。如果单元对象没有关联的重用标识符,则不会调用此方法。如果重写此方法,则必须确保调用超类实现。

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

}

答案 1 :(得分:0)

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

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

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

        return arrayThatcontainsShopImages.count
}

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

使用SDWebImage可以更胜一筹。使用此库查看以下代码,您只需创建一个UIImageView实例。然后使用这个库,你可以将图像直接下载到imageview实例,并访问图像,你可以使用UIImageView类的imageView.image属性

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