Search code examples
iosswiftuitableviewnstimercagradientlayer

First and Last Cell Change Color When Scrolling in UITableView


I have a list of custom cells that have specific colors, which rely on the time. A timer runs to keep each cell's color up to date. The first and last cells in the tableView have each other's colors every time I scroll all the way to the top or the bottom of the tableView. For example, if the first cell is green and the last cell is red, then the first cell becomes red when I scroll up and changes to green after a second. This is my timer:

// Refreshes the labels every second to update the time
    timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { [weak self] _ in
        if let s = self, let tableView = s.tableView, let indexPaths = tableView.indexPathsForVisibleRows {
            for indexPath in indexPaths {
                guard let cell = tableView.cellForRow(at: indexPath) as? PersonCell else { return }
                let person = s.people[indexPath.section]
                let day = dayOfWeekIn(timeZone: person.timeZone)

                // update text of cell and check some conditions to set the gradient of the cell accordingly
        }
    })

I also configure my cells in cellForRowAt, but these configurations are not related to the background of the cell, so I don't think it is the cause of the problem. I would really appreciate it if someone could help me fix this.


Solution

  • Cells are reused...

    That means, when you scroll down and then back up, you can get a cell that had its background color changed to red while it was at, say, row 20, but now is being used for row 0.

    You need to explicitly set the desired background color in cellForRowAt every time.

    EDIT

    You can use your current method of changing the background color, but you'll have to track the current background color as part of your dataSource.

    For example, add a currentBackgroundColor property to your Person class. When you do this:

    // update text of cell and check some conditions to set the gradient of the cell accordingly
    

    you would also do (something like):

    data[indexPath.section].currentBackgroundColor = UIColor.green
    

    When you get a call to cellForRowAt, you would then also do:

    cell.backgroundColor = data[indexPath.section].currentBackgroundColor
    

    Without seeing your actual data source / structure, it's difficult to give you an explicit example, but that's the idea.