当我向下滚动并返回时,我的数据在 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 = ""
}
当我在我的 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 = ""
}