jat
jat

Reputation: 347

Swift Tableview reusable cell issue

I am having an issue with what I think is reusable cells in a tableview cell, unfortunately I can't work out how to force the state of the cell. I am fairly sure this is the issue because when I reload the tableview everything is displayed correctly. It's only when I scroll that I start to see issues, if I once again reload the display corrects itself.

This is the correct display :

enter image description here

and the incorrect display after scrolling about :

enter image description here

my cellForRowAt code :

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "historyGoalCell", for: indexPath)
        
        let name = items[indexPath.section][indexPath.row].name
        let date = dateManager.dateAsString(for: items[indexPath.section][indexPath.row].date!)
        
        
        if tempDate != date {
            
            // show header
            
            cell.textLabel?.text = date
            
            tempDate = date
            
        } else {
            
            // don't show header
            
            cell.textLabel?.text = ""
              
        }
        
        cell.detailTextLabel?.text = "\(date),\(name ?? "")"
        
        return cell
    }

Thanks for any help, I have been stuck with this for a couple of days, very new to TableViews - thanks

Upvotes: 0

Views: 580

Answers (1)

AntiVIRUZ
AntiVIRUZ

Reputation: 342

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

can be invoked in any order. It isn't called consistently from 1 to N, so logic with tempDate works not as planned. Better do some pre-work and make an array with indexes where you place headers. For example

struct Pair : Hashable {
    var i : Int
    var j : Int
}

//Somewhere one time before the first reloadData

var hasIndex : Set<Pair> = []
var tempDate: Date = Date.distantPast

for i in 0..<sections {
    for j in 0..<rows[i] {
        let name = items[i][j].name
        let date = dateManager.dateAsString(for: items[i][j].date!)
        if tempDate != date {
            hasIndex.insert(Pair(i: i, j: j))
            // OR items[i][j].showHeader = true
            tempDate = date
        } else {
            // OR items[i][j].showHeader = false
        }
    }
}

...

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

    let cell = tableView.dequeueReusableCell(withIdentifier: "historyGoalCell", for: indexPath)
    let name = items[indexPath.section][indexPath.row].name
    let date = dateManager.dateAsString(for: items[indexPath.section][indexPath.row].date!)

    if hasIndex.contains(Pair(i: indexPath.section, j: indexPath.row)) {
    // OR if items[indexPath.section][indexPath.row].showHeader {
        cell.textLabel?.text = date
        tempDate = date
    } else {
        cell.textLabel?.text = ""
    }

    cell.detailTextLabel?.text = "\(date),\(name ?? "")"

    return cell
}

Upvotes: 1

Related Questions