Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift UITableViewCell子类单元格中的图像错误或旧图像错误_Swift_Xcode_Uitableview - Fatal编程技术网

Swift UITableViewCell子类单元格中的图像错误或旧图像错误

Swift UITableViewCell子类单元格中的图像错误或旧图像错误,swift,xcode,uitableview,Swift,Xcode,Uitableview,所以伙计们,我曾经遇到过Massive-View-Controller问题,特别是在使用UITableView时,现在我正在将一个旧的应用程序更改为更具模态的应用程序。以前,我习惯于将整个单元格设置为cellforrowatindexpath。设置标签,下载图片等 现在我使用正确的方法设置UITableViewCell子类。但我也有一个问题,重复使用单元格,在更新/下载新图片时留下旧图片,我想我已经解决了,但我也注意到,这有点像是把错误的图片放在错误的单元格中,然后在快速滚动时更新到正确的图片

所以伙计们,我曾经遇到过
Massive-View-Controller
问题,特别是在使用
UITableView
时,现在我正在将一个旧的应用程序更改为更具模态的应用程序。以前,我习惯于将整个单元格设置为
cellforrowatindexpath
。设置标签,下载图片等

现在我使用正确的方法设置
UITableViewCell
子类。但我也有一个问题,重复使用单元格,在更新/下载新图片时留下旧图片,我想我已经解决了,但我也注意到,这有点像是把错误的图片放在错误的单元格中,然后在快速滚动时更新到正确的图片

之前,我可以这样做,以确保图像更新在正确的细胞。在视图控制器中设置整个单元格时,如下所示

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier")

    cell.title = "Cool title"

    imageLoader.obtainImageWithPath(imagePath: viewModel.image) { (image) in
        // Before assigning the image, check whether the current cell is visible for ensuring that it's right cell
        if let updateCell = tableView.cellForRow(at: indexPath) {
            updateCell.imageView.image = image
        }
    }    
    return cell
}
现在我几乎只在
viewcontroller
上有这个

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell : RestCell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! RestCell

    // Pass data to Cell :) clean the mess at the View Controller ;)
    cell.restData = items[indexPath.row]

    return cell
}
我有一个UITableViewCell子类

class RestCell: UITableViewCell {

    @IBOutlet var img : UIImageView!
    @IBOutlet var lbl : UILabel!
    @IBOutlet var lbl_tipocomida: UILabel!
    @IBOutlet var lbl_provincia: UILabel!
    @IBOutlet var img_orderonline: UIImageView!
    @IBOutlet var img_open: UIImageView!
    @IBOutlet var imgalldelivery: UIImageView!
    @IBOutlet var img_reservasonline: UIImageView!

    // get data and update.
    var restData: RestsModel!  {
        didSet {
            // default img early placeholder set. Eliminates showing old pic in cell reuse
            self.img.image = UIImage(named: "60x60placeholder.png")
            // Update all values func
            updateUI()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Default image placeholder
       //self.img.image = UIImage(named: "60x60placeholder.png")

    }
    // required init.
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!

        // Color of selected.
        let myCustomSelectionColorView = UIView()
        myCustomSelectionColorView.backgroundColor = UIColor(red: 234.0/255.0, green: 46.0/255.0, blue: 73.0/255.0, alpha: 0.1) //UIColor(netHex:0xFFFF434)
        selectedBackgroundView = myCustomSelectionColorView   
    }   

    fileprivate func updateUI() {

        if (self.restData.image != nil  &&  self.restData.image != "") {
            ImageLoader.sharedLoader.imageForUrl(urlString:self.restData.image, completionHandler:{(image: UIImage?, url: String) in
                self.img.contentMode = UIViewContentMode.scaleAspectFit
                self.img.image = image
            })
        } else {
            self.img.image = UIImage(named: "60x60placeholder.png")
        }

        self.lbl.text = restData.name as String
        self.lbl_provincia.text = restData.provincia as String
        self.lbl_tipocomida.text = restData.tipocomida as String

        // check if has alldelivery enabled, show Alldelivery logo
        if( self.restData.reservaonline == "1") {
            self.img_reservasonline.isHidden = false
            self.img_reservasonline.image = UIImage(named: "icon_reserva_on")

        } else {
            self.img_reservasonline.isHidden = true
            self.img_reservasonline.image = UIImage(named: "icon_reserva_off")
        }

        // check if has orderonline, show ordeonline text
        if ( self.restData.orderonline == "1") {
            self.img_orderonline.isHidden = false
        } else {

            self.img_orderonline.isHidden = true
        }

        // check if has schedule, display if open or close

        if (self.restData.hasSchedule == true) {

            if ( self.restData.openNow == true) {
                self.img_open.image = UIImage(named:"icon_open")
            }  else {
                self.img_open.image = UIImage(named:"icon_close")
            }

            self.img_open.isHidden = false
        } else {

            self.img_open.isHidden = true
        }

    }

}

我从
UITableViewVCell
子类调用图像下载,并将其设置在那里。如何确保图像仅设置为正确的单元格?

这是由于竞争条件造成的(这很常见)

根据您当前的解决方案,我将这样做:

  • 重新加载单元格数据时删除上一个图像。加载新图像后,您可以执行类似于self.myUIImage.image=nil的操作
  • 检查图像下载后单元格是否仍然可见:
    • 如果已加载,则添加图像
    • 如果没有,那么忽略它。如果您正在缓存它,它将在下次使用它时被缓存(这将是另一个主题)
您可能需要检查一些类似的问题,例如:


我建议您使用第三方库加载带有url的图像,例如
翠鸟
。它将为您处理缓存和取消加载

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let data = dataSource[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier") as! ACell
    cell.update(data)
    return cell
}
细胞看起来是这样的

import Kingfisher
class ACell: UITableViewCell {
    @IBOutlet fileprivate weak var backgroundImageView: UIImageView!

    fileprivate func reset() {
        backgroundImageView.image = nil
    }

    func update(_ data: ATypeOfData) {
        reset()
        let resource = ImageResource(downloadURL: url)
        backgroundImageView.kf.setImage(with: resource)
    }
}
你失败的原因是你误解了重复使用电池

let updateCell = tableView.cellForRow(at: indexPath)

updateCell
可以是另一个单元格,其中包含要使用的单元格。它可以只是一个重复使用的随机单元。如果确实要跟踪单元格,则需要设置属性并检查
cellForRowAt
中的属性是否与图像加载闭包中的属性相同。我真的建议您使用我附带的模式。

与这个问题相比:嘿,gabox,就像我的问题中所显示的那样,我知道如何在使用视图控制器中的*set all方法时检查单元格是否正确可见,但我如何从uitableviewcell子类中做到这一点?您需要一个委托(记住它应该是弱的)对于你的表格视图,你会为此杀了我。你能详细说明一个完整的例子吗?我发现主要是另一种方式,一个委托,因此单元格在视图控制器中执行某些操作…你能给出任何例子吗?检查图像下载后单元格是否仍然可见:如果它已加载,则添加图像。if不要忽略它。如果您正在缓存它,它将在下次使用它时被缓存(这将是另一个主题).嘿,ryan,谢谢你提供了一个使用翠鸟的完整示例。我真的很感激。我不想用第三方库来考虑这个问题。你知道如何手动操作吗?如果做不好,我最后的办法肯定是使用翠鸟加载图像和缓存并不像你想的那么简单。另外,这是不同的主题。有很多好东西d解决了图像缓存问题。