如何向 UITableView 中的单元格添加复选标记(使用自定义 UITableViewCell 子类和 dequeueReusableCell)

How to add a checkmark to cells in UITableView (using a custom UITableViewCell subclass and dequeueReusableCell)

我想在我的 Table 视图单元格中添加复选标记。我想只在我的 didSelectRowAt 方法中实现 cell.accessoryType = UITableViewCellAccessoryCheckmark,但是在使用自定义 UITableViewCell 子类时我无法让它工作。

自定义单元格:

class TableCell: UITableViewCell {
    
    @IBOutlet weak var tableLabel: UILabel!
    
    var arrayOneToDisplay:ArrayOne?
    let arrayOne = ArrayOne()
    
    func displayTable(_ currentArrayOne:ArrayOne) {
        
        // Keep a reference to the cell
        arrayOneToDisplay = currentArrayOne
        
        // Get the Table Cells data
        var tableCell = arrayOne.tableCells
        
        // Set the instructionLabel
        tableLabel.text = currentArrayOne.tableCells![0]
        
    }

ViewController:

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        // Make sure the array contains at least 1 item
        guard arrayOne.count > 0 else {
            return 0
        }
        
        // Return the number of items for this array
        let currentArrayOne = arrayOne[currentArrayOneIndex!]
        
        if currentArrayOne.tableCells != nil {
            return currentArrayOne.tableCells!.count
        }
        else {
            return 0
        }

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // Get a cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
        
        // Get the instruction that the tableView is asking about
        let tableLabel = cell.tableLabel
        
        if tableLabel != nil {
            
            let currentArrayOne = arrayOne[currentArrayOneIndex!]
            
            if currentArrayOne.tableCells != nil && indexPath.row < currentArrayOne.tableCells!.count {
                // Set the text for the label
                tableLabel!.text = currentArrayOne.tableCells![indexPath.row]
            }
        }
        
        // Return the cell
        return cell

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

    }

}

当我尝试在 ViewController 中实现 cell.accessoryType 时,Xcode 无法识别 accessoryType。我相信这是因为我的方法是针对 UITableView 而不是 UITableViewCell,所以使用自定义单元格的额外问题让我有些困惑。非常感谢任何指导!

不确定您要做什么。 table视图通常的做法是不在数组中保存tableviewcell。模型-视图-控制器(MVC)方式是将单元格的内容(文本、图像、checkedOrNotChecked)保存在viewcontroller(数组就是模型)内部的结构或对象数组中。然后在 CellForRow 中,使用 array[indexPath.row] 元素设置单元格的内容,如果 checkedOrNotCheckindicator 设置 cell.accessoryType 为复选标记(单元格是视图)。 在 didSelectRow 中,您只需设置 indexPath.row 元素的 checkOrNotCheck 指示符,然后重新加载 table 视图或重新加载位于 indexPath 的单元格。 Thé ViewController 是 MVC

中的控制器

您应该在 cellForRowAt 方法中设置您的 accessoryType,尝试将其重写为:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell

        cell.accessoryType = .checkmark
        
        guard let arrayOneIndex = currentArrayOneIndex, arrayOneIndex < arrayOne.count else { return cell }

        let currentArrayOne = arrayOne[arrayOneIndex]

        guard let tableCells = currentArrayOne.tableCells, indexPath.row < tableCells.count else { return cell }

        cell.tableLabel.text = tableCells[indexPath.row]
        
        return cell
    }

抱歉,您的做法完全错误。永远不要使用 view 作为数据源类型。不要。

创建一个 模型,这是一个具有 nameisSelected 属性的简单示例

struct Model {
    let name : String
    var isSelected = false
}

并在 controller ViewController 中声明一个包含 Model 个实例的数据源数组

var arrayOne = [Model(name: "Foo"), Model(name: "Bar"), Model(name: "Baz")]

numberOfRows 的扩展中只是 return 数组中的项目数(你的 guard 表达式根本没有意义),在 cellForRow 中设置复选标记取决于 isSelecteddidSelect 切换 isSelected 属性 并重新加载行。

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return arrayOne.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // Get a cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
        
        // Get the item of the data source array
        let item = arrayOne[indexPath.row]
        
        // update the view
        cell.tableLabel = item.name
        cell.accessoryType = item.isSelected ? .checkmark : .none   
        
        // Return the cell
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // toggle isSelected of the row in the model
        arrayOne[indexPath.row].isSelected.toggle()
      
        // reload the row to update the view
        tableView.reloadRows(at: [indexPath], with: .none)   
    }

}

在自定义单元格中只声明出口,没有其他东西

class TableCell: UITableViewCell {
    
    @IBOutlet weak var tableLabel: UILabel!
        
}

这种方法的好处是 modelview 总是同步的。