如何在 Swift 5 中为基于单元格的 NSTableVew 中的单个行着色

How to colour individual rows in Cell-Based NSTableVew in Swift 5

我正在尝试显示 NSTableView 中的项目,但其中之一(之前由操作激活的项目(其名称存储在 alreadyActivatedItem 变量中)应该被禁用并显示带有红色文字。

到目前为止,我设法使禁用正常工作。

我无法将已激活的项目着色为红色文本。我下面的代码会将所有单元格的文本涂成红色。

extension PreferencesViewController: NSTableViewDelegate {
    
    // disable selecting the already activated item
    func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
                        
        return !(myArray[row].name == alreadyActivatedItem)
    }
    
    // colouring the already activated item in red (it is also disabled)
    func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int) {
        
        guard let c = cell as? NSTextFieldCell else {
            return
        }

        if c.stringValue == alreadyActivatedItem {
            c.textColor = .red
        }

    }
}

我也试过其他方法:

// colouring the already activated item in red (it is also disabled)
func tableView(_ tableView: NSTableView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, row: Int) {

    guard let c = tableColumn?.dataCell(forRow: row) as? NSTextFieldCell else {
        return
    }
    
    if c.stringValue == alreadyActivatedRow {
        c.textColor = .red
    }
}

在这两种情况下,所有行都带有红色文本:

see as all items are red text

调试时,我可以看到:

那么为什么所有的项目仍然是红色的?

那怎么实现我的目标呢?

(Xcode 11.3.1, Swift 5.1.3)

细胞被重复使用。您必须添加一个 else 子句以将颜色始终设置为定义的状态。

if c.stringValue == alreadyActivatedItem {
    c.textColor = .red
} else {
    c.textColor = .black
}

或更简单

 c.textColor = c.stringValue == alreadyActivatedItem ? .red : .black

我什至推荐基于 table 视图和 Cocoa 绑定的视图。