如何正确更新TableViewCells

时间:2017-03-23 15:33:19

标签: ios uitableview core-graphics

让TableView的单元格显示正确的选择状态的正确程序是什么?下表列出了我作为UIButton的子类制作的这些自定义指标。当点击didSelectRowAtIndexPath时,它们在点亮和关闭之间切换。 tableView的dataSource是一个Dictionaries数组,字典包含与每个单元格状态相关的信息。

我正在努力解决的挑战是,当我滚动列表时,不正确的单元格会亮起或关闭,我怀疑它是单元重用的函数。

enter image description here

我已经尝试将代码放在willDisplayCellForRowAtIndexPath中。我想我之前已经解决了这个问题,但我仍然坚持这个问题。

以下是tableView方法

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

        let cell = self.tableView.dequeueReusableCell(withIdentifier: "HourlyWaterCell", for: indexPath) as! HourlyWaterCell
        let dictionary = dataSource[indexPath.row]

        if let startTime = dictionary["startTime"] as! Date? {
            cell.timeLabel.text = dateFormatter.string(from: startTime)
        }

        return cell
    }

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

    tableView.deselectRow(at: indexPath, animated: true)
    var dictionary = dataSource[indexPath.row]

    let buttonState = (tableView.cellForRow(at: indexPath) as! HourlyWaterCell).button.completed
    if buttonState == true {
        (tableView.cellForRow(at: indexPath) as! HourlyWaterCell).button.completed = false
        cellStates[indexPath.row] = false
        dictionary["selected"] = false
    }
    else {
        (tableView.cellForRow(at: indexPath) as! HourlyWaterCell).button.completed = true
        //cellStates[indexPath.row] = true
        dictionary["selected"] = true

        graphView.fill(column: 1)
    }

}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

    let dictionary = self.dataSource[indexPath.row]
    if let selectionState = dictionary["selected"] as! Bool? {
        if selectionState == true{
            //cell.button.completed = true
            cell.setSelected(true, animated: true)
        } else {
            //cell.button.completed = false
            cell.setSelected(false, animated: true)
        }
    }
}

这是自定义按钮类

import UIKit

@IBDesignable
class WaterButton: UIButton {

    @IBInspectable var fillColor: UIColor = .green
    @IBInspectable var greyColor: UIColor = .gray
    @IBInspectable var completed = false
    let lineWidth: CGFloat = 2.0
    let π = CGFloat(M_PI)   //option P for π

    override func draw(_ rect: CGRect) {
        if completed {
            drawStrokedCircle(percentRadius:0.5, color: fillColor, filled: true)
            drawStrokedCircle(percentRadius:0.8, color: fillColor, filled: false)
        } else {
            drawStrokedCircle(percentRadius:0.5, color: greyColor, filled: false)
        }
    }

    func drawStrokedCircle(percentRadius: CGFloat, color: UIColor, filled: Bool) {
        // 1
        let center = CGPoint(x:bounds.width/2, y: bounds.height/2)

        // 2
        let radius: CGFloat = ((max(bounds.width, bounds.height) / 2.0 ) * percentRadius)

        // 3
        //let arcWidth: CGFloat = 76

        // 4
        let startAngle: CGFloat = 0
        let endAngle: CGFloat =  2 * π

        // 5
        let path = UIBezierPath(arcCenter: center,
                                radius: radius,
                                startAngle: startAngle,
                                endAngle: endAngle,
                                clockwise: true)

        // 6
        path.lineWidth = 2.0
        color.setStroke()
        path.stroke()

        if filled {
            fillColor.setFill()
            path.fill()
        }
    }
}

2 个答案:

答案 0 :(得分:0)

我做了完全相同的事情,但是它已经有一段时间了,我再也无法访问该代码。

但我没有在willDisplay方法中设置选择。相反,我在cellForRowAt中设置了选择状态。

如果我自己在桌面视图单元格中选择了一个单元格,那么我可能需要执行簿记。希望这有帮助!

:)

答案 1 :(得分:0)

您可以将WaterButton的选定状态(completed)存储在您的委托中,然后在每次按住按钮的单元格(cellForRowAtIndexPath)时恢复按钮的状态。观察您已完成的'的价值变化。 WaterButton中的财产。

@IBInspectable var completed = false {
    didSet {
        if completed == true {
            drawStrokedCircle(percentRadius:0.5, color: fillColor, filled: true)
            drawStrokedCircle(percentRadius:0.8, color: fillColor, filled: false)
        } else {
            drawStrokedCircle(percentRadius:0.5, color: greyColor, filled: false)
        }
    }
}

还原: 在tableview的委托中添加一个ivar:

var cellButtonStates : [NSInteger : Bool]?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "HourlyWaterCell", for: indexPath) as! HourlyWaterCell
    let dictionary = dataSource[indexPath.row]
    if let completed = cellButtonStates?[indexPath.row] {
        cell.button.completed = completed
    }
}

显然,每次用户选择一个单元格时都必须更新cellButtonStates

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
/* you can perform extra evaluation to avoid 
iterating to cellButtonStates if not needed */
    for (i,_) in self.cellButtonStates.keys.enumerated() {
        self.cellButtonStates[i] = false
    }
    self.cellButtonStates[indexPath.row] = true
    //call reloadData
}

如果您想坚持使用代码(使用isSelected),我建议您覆盖HourlyWaterCell中的isSelected属性,如下所示:

class HourlyWaterCell: UITableViewCell {
override var isSelected: Bool {
    didSet {
        button.completed = isSelected;
    }
}

以上代码均未经过测试。