1

在我的习惯UITableViewCell设置属性时,如果没有标签,它将创建一个标签并设置文本等。如果标签已经存在,它不应该做任何事情。奇怪的是,当我第一次点击单元格时,它会创建应有的标签。但是当我再次点击单元格时,标签消失了。我已经在一个干净的项目中重新创建了它,并且正在发生同样的事情。这种奇怪行为的原因是什么?

自定义表视图单元:

class TableViewCell: UITableViewCell {

    var numberLabel: UILabel!
    var views = [String: UILabel]()

    var number: Int = 5 {
        didSet {
            println("AMOUNT: Accessed")
            if numberLabel == nil {
                println("AMOUNT: Amount is nil")

                // Create amount label
                numberLabel = UILabel()
                if number > 0 { numberLabel.text = String(number) }
                numberLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
                contentView.addSubview(numberLabel)
                views["amount"] = numberLabel

                // Amount label constraints
                contentView.addConstraint(NSLayoutConstraint(item: numberLabel, attribute: .CenterY, relatedBy: .Equal, toItem: contentView, attribute: .CenterY, multiplier: 1, constant: 0))
                contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[amount(40)]-8-|", options: nil, metrics: nil, views: views))
            } else {
                println("AMOUNT: Nothing should be changing or happening \n")
            }
        }
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("NSCoding not supported")
    }

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

视图控制器:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    var items = [Int]()
    var amount = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")
    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as TableViewCell

        cell.number = amount

        return cell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        amount++
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    }
}

编辑:作为对评论的回应,我的控制台显示:

NUMBER: Accessed
NUMBER: Number is nil
NUMBER: Accessed
NUMBER: Number is nil                                 << label shows "1"
NUMBER: Accessed
NUMBER: Nothing should be changing or happening       << label disappears.

NUMBER: Accessed
NUMBER: Nothing should be changing or happening       << label shows "1" again

NUMBER: Accessed
NUMBER: Nothing should be changing or happening       << label disappears.

NUMBER: Accessed
NUMBER: Nothing should be changing or happening       << label shows "1" again

NUMBER: Accessed
NUMBER: Nothing should be changing or happening       << label disappears.

我还将背景更改为一种颜色,它就消失了。我想这与oldValuedidSet 的有关。当willSet我将值更改为newValue. 但是,当我使用“旧值”时,什么都没有发生。

4

2 回答 2

1

我相信这是由于重复使用相同的两个单元格:

您的表格只有一行,但您最终从头开始创建了两个单元格,这从初始输出中可以清楚地看出。它可能会创建两个,因为您在使用第一个单元格时重新加载,从而强制创建第二个单元格。

第一个单元格 (A) 将具有数字 0 和空白标签。第二个单元格 (B) 将具有数字 1 和一个带有 1 的标签。

当您进行下一次选择时,表格会重复使用具有空白文本的单元格 A。无论数字是多少,这始终是空白的,因为您永远不会为已经有标签的单元格重置数字。

当您进行下一次选择时,表格会重用单元格 B,其中包含带有 1 的文本。

然后这种模式会重复,因为您总是在使用一个单元格时调用 reload 来重用另一个单元格。因此A,B,A,B......

要解决此问题,您需要在每次设置数字时设置标签内容。

于 2015-04-07T21:39:03.917 回答
1

与其对您的设置进行故障排除,让我指出其他内容:通过依赖“在场”标签,您实际上是在使用 UI 元素作为数据源。这违反了 MVC(模型视图控制器)模式,并可能导致各种麻烦,包括您的情况。

我喜欢让表格视图单元格具有强大属性的机制,我可以像您在cellForRowAtIndexPath. 它产生简洁而漂亮的代码。它将数据逻辑与显示分开,显示在其所属的视图中。

所以对于 cell 子类,我建议不要创建和销毁 UI 元素,因为这不是很有效。相反,在 Storyboard 中设置您需要的所有 UI 元素,然后在 Interface Builder 中将它们连接起来。在属性的 setter 中,检查属性的值number并根据需要更改 UI 元素。如果要隐藏标签,请将其hidden属性设置为true

理想情况下,您的表格视图控制器应该知道索引路径中单元格的状态。单元格应该只是完成正确显示此状态的工作。

于 2015-04-07T21:25:03.850 回答