滚动后某些表格视图单元格内容消失(swift)

Posted

技术标签:

【中文标题】滚动后某些表格视图单元格内容消失(swift)【英文标题】:Some tableview cell content disappears after scroll (swift) 【发布时间】:2017-07-17 13:38:29 【问题描述】:

下面是我的自定义单元格类:

class AthleteTableViewCell: UITableViewCell 

var myLabel1: UILabel!
var myLabel2: UILabel!
var profile: UIImageView!
var star = StarButton()
var touched = false

required init(coder aDecoder: NSCoder) 
    fatalError("init(coder:)")


override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    let gap : CGFloat = 10
    let labelHeight: CGFloat = 30
    let labelWidth: CGFloat = 150
    let lineGap : CGFloat = 5
    let label2Y : CGFloat = gap + labelHeight + lineGap


    myLabel1 = UILabel()
    myLabel1.frame = CGRect(x: gap, y: gap, width: labelWidth, height: labelHeight)
    myLabel1.textColor = UIColor.black
    contentView.addSubview(myLabel1)

    myLabel2 = UILabel()
    myLabel2.frame = CGRect(x: gap * 5, y: label2Y, width: labelHeight, height: labelHeight)
    myLabel2.textColor = UIColor.white
    myLabel2.textAlignment = .center
    myLabel2.backgroundColor = UIColor.flatMint()
    myLabel2.layer.cornerRadius = 15.0
    myLabel2.clipsToBounds = true
    contentView.addSubview(myLabel2)

    profile = UIImageView()
    profile.image = UIImage()
    profile.frame = CGRect(x: bounds.width - gap, y: bounds.height / 2, width: bounds.height * 1.25, height: bounds.height * 1.25)
    profile.layer.cornerRadius = (bounds.height * 1.25) / 2
    profile.layer.masksToBounds = true
    contentView.addSubview(profile)

    if (touched != false) 
        star.isSelected = true
        star.frame = CGRect(x: gap, y: label2Y, width: labelHeight, height: labelHeight)
        contentView.addSubview(star)
     else 
        star.frame = CGRect(x: gap, y: label2Y, width: labelHeight, height: labelHeight)
        contentView.addSubview(star)
        star.isEnabled = true
    

以下是创建我的单元格的方法:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = AthleteTableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "myCell")

    cell.myLabel1.text = "\(myArray[indexPath.row])"
    cell.myLabel1.textColor = UIColor.white
    cell.myLabel2.isHidden = true

    cell.profile.image = UIImage(named: cell.myLabel1.text!)

    cellArray.append(cell)

    if (cell.touched) 
        cell.star.isSelected = true
     else 
        cell.star.isOpaque = true
    

    cell.backgroundColor = UIColor(white: 1, alpha: 0.2)

    return cell

下面是选择一个单元格的方法,该单元格会触发一个动画,我希望它的最终状态保留在 tableview 单元格上。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    makeSelection(tableView, didSelectRowAt: indexPath)


func makeSelection(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    let cell = tableView.cellForRow(at: indexPath) as! AthleteTableViewCell
    cell.selectionStyle = UITableViewCellSelectionStyle.none

    if(selectionArray.contains(myArray.object(at: indexPath.row))) 
        //Popping selection off of the stack and updating all labels
        updateLabels(tableView: tableView)
        selectionArray.remove(myArray[indexPath.row])
        cell.star.isFavorite = false
        cell.myLabel2?.isHidden = true
        //need to somehow implement all of the rank labels decreasing by one if I deselect someone
        cell.touched = false
        //updateLabels(tableView: tableView)
     else 
        selectionArray.add(myArray[indexPath.row])
        cell.touched = true
        let rank = selectionArray.count
        cell.myLabel2.isHidden = false
        cell.myLabel2?.text = "\(rank)"
        cell.star.isFavorite = true
    

这是您选择单元格时的照片:

这是同一个单元格在向下滚动后的照片,这样就看不见了,然后再向后滚动:

这里显然出了点问题 - 我在自定义表格视图单元格类中添加了“已触摸”布尔值,假设单元格可能正在重绘,并且无法知道是否应该让该星形动画或者不是,所以它被认为是 nil,但该修复似乎不起作用(也许我正在做某事但实施不正确?)

如果您知道这里发生了什么,请告诉我!非常感谢!!!

【问题讨论】:

这看起来像经典的细胞回收错误。 UITableView 不在屏幕外时不会保留细胞,而是将它们回收再利用。您无法将有效模型数据存储在单元格中。 理想情况下,您应该将触摸的部分存储在数据存储区而不是单元格中。您的手机不用于存储任何信息。因此,每次单击您的单元格时,您都需要为该特定项目更新数据存储区,说 touch == true,然后重新加载 tableview。 @kapsym 当你说“为那个特定项目更新你的数据存储”时,你是什么意思? 所以您必须使用对象数组来填充您的表格视图,对吧?该对象数组是 tableView 的数据源。因此,如果您有一个自定义对象来表示您的信息,请在该对象中添加touched 参数。如果您没有自定义对象,请创建一个具有名称、触摸等作为参数的对象。因此,当您进行此选择时,从 didselectCell 方法中获取 indexpath.row,然后转到您的数组并更新该特定位置的自定义对象,说 touch = true。并刷新tableview @ S.Billings 添加了这些步骤作为答案,为您指明了正确的道路。看看有没有帮助。 【参考方案1】:

您的代码存在各种问题。在您的tableView(_:cellForRowAt:) 方法中,您应该调用dequeueReusableCell(withIdentifier:for:)

您不应尝试从单元格中读取数据以加载内容。您应该将状态数据保存到某种数据模型中。数组适用于具有单个部分的表视图,数组数组适用于分段表视图。

关于如何使用表格视图的教程数不胜数。你需要去读一读。

【讨论】:

我的 tableview 确实有一个部分。因此数组。 好的,但是您的cellForRow(at:) 方法不会检查您的选定单元格数组,以查看它是否应该将单元格设置为选定的。除了不打电话给dequeueReusableCell(withIdentifier:for:)【参考方案2】:

这里将其作为一个逐步的过程提及它作为答案

1) 为您的数据创建结构

struct Profile 
var personName: String?
var photoURL: String?
var rank: String?
var isTouched: Bool?

// add init method and stuff

2) 使用这些 Profile 元素填充您的数组。这样最终你就有了一个配置文件数组。

3) 使用此数组来填充您的表格视图,其中每个单元格元素都从 Profile 对象中获取数据。

4) 在您的 cellForRowAt 方法中使用 dequeueReusableCell(withIdentifier:for:) 来初始化您的单元格并分配值

5) 如果对于该特定配置文件,isTouched 为真,则显示

cell.star.isFavorite = true

否则设置为假

6) 在您的 didSelectRow 中,获取 indexpath.row,然后在您的配置文件数组中根据您对该特定行的需要设置 Profile.isTouched=true/false 并相应地切换。使用新的配置文件对象更新您的配置文件数组。

7) 刷新表格视图。

【讨论】:

以上是关于滚动后某些表格视图单元格内容消失(swift)的主要内容,如果未能解决你的问题,请参考以下文章

Swift:每次重新加载时都会一次又一次地添加表格视图单元格内容?

UITableViewController 的单元格内容消失

集合视图单元格内容是分层的

移除单元格附件后,如何将微调器与单元格内容视图居中?

QML - 获取表格视图单元格内容

表格内容在使用子视图的自定义单元格的 TableView 滚动上消失 - Swift