Set UiCell text color in TableView according indexPath Swift

Viewed 57

I'm trying to display on screen some logs through UiTableView and I want to set a red text color to those hasPrefix "root" as following :

var logList: [String] = []

...

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.logList.count
    }

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

        let cell = tableview.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ItemLogCell
        cell.itemLogLabel.text = self.logList[indexPath.row]
        
        print(indexPath.row)
        print(self.logList[indexPath.row].hasPrefix("root"))

        if (self.logList[indexPath.row].hasPrefix("root")) {
            cell.itemLogLabel.textColor = UIColor.red
        }
        
        return cell
    }

The problem is even when the prefix condition is false, text color become red and only for some row.

The more I scroll the more there are random red logs. How can I fix this ?

4 Answers

Use instead different UITableViewDelegate callback for that

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    guard let cell = cell as? ItemLogCell else { return }

    print(indexPath.row)
    print(self.logList[indexPath.row].hasPrefix("root"))

    if (self.logList[indexPath.row].hasPrefix("root")) {
        cell.itemLogLabel.textColor = UIColor.red
    }

}

You can do something like this to reset the color of the other lines :

if (self.logList[indexPath.row].hasPrefix("root")) {
   cell.itemLogLabel.textColor = UIColor.red
}
else {
   cell.itemLogLabel.textColor = UIColor.white
}

Because UITableViewCell is basically reusable. Imagine that you are seeing there are 6 cells in the screen, index 0 to 5. When you scroll to cell with index 6, the cell with index 0 will be hidden. TableView will not create a new UITableViewCell for the cell 6, it will waste the device's memory. Instead, tableview will dequeue the cell 0 and reuse it. So, cell 6 will has the default value of cell 0. To fix this issue, you will need to set the color again, of the cell that does not has prefix "root"

if (self.logList[indexPath.row].hasPrefix("root")) {
    cell.itemLogLabel.textColor = UIColor.red
} else {
    cell.itemLogLabel.textColor = UIColor.black
}

As pham hai explain cells are reusable so You should consider else case as well. Shorty

    let cellColor = cell.itemLogLabel.textColor
    self.logList[indexPath.row].hasPrefix("root") ? cellColor = .red : cellColor = .black
Related