Maha
Maha

Reputation: 529

Duplication in values of tableView when Scrolling Swift

I have a tableView to display timings of week days

timingsArray is used in tableView to display timings

timingsArray of type timingObj

class timingObj {
    var dayNo: Int?
    var open: String?
    var close: String?
    var dayName: String?

     init(json: JSON){
        // to take data from json
    }

    init(name: String, number: Int){
        self.dayName = name
        self.dayNo = number
    }
}

in tableView i want to display all days and their timings, if the day does not have timing then timing cell will be empty

let cell = tableView.dequeueReusableCellWithIdentifier("TimingsCell", forIndexPath: indexPath) as! timingCell     
            let timings = self.Details!.timingsArray
            let dayTime = timings[indexPath.row]
            cell.dayLabel.text = dayTime.dayName
            if dayTime.open != nil && dayTime.close != nil {
                cell.timeLabel.text = "\(convertTimeFormat(dayTime.open!)) - \(convertTimeFormat(dayTime.close!))"
            }
            return cell

This is the class of the cell

class timingCell: UITableViewCell {

    @IBOutlet weak var dayLabel: UILabel!

    @IBOutlet weak var timeLabel: UILabel!

}

e.g Tuesday and Thursday only have timings

the problem is when i scroll up and down, timing value of Tuesday gets duplicated in Wednesday, and when i keep scrolling, timing values get duplicated too in other cells

Any ideas? Thank you in advance

Upvotes: 3

Views: 7974

Answers (3)

Koen.
Koen.

Reputation: 26939

Adding a prepareForReuse method to your cell class in which you reset the cell to it's initial state has the same effect as @CH Uck's answer

For example:

func prepareForReuse() {
   super.prepareForReuse()
   self.dayLabel.text = ""
   self.timeLabel.text = ""
}

See also: prepareForReuse in Apple developer documentation.

Upvotes: 7

Ramy Kfoury
Ramy Kfoury

Reputation: 947

You should implement prepareForReuse in your custom cell class, in which you reset what needs to be reset. For example:

class timingCell: UITableViewCell {

    @IBOutlet weak var dayLabel: UILabel!

    @IBOutlet weak var timeLabel: UILabel!

    func prepareForReuse() {
        super.prepareForReuse()
        cell.timeLabel.text = nil
        cell.dayLabel.text = nil
    }
}

Upvotes: 9

hakkurishian
hakkurishian

Reputation: 276

From the Apple Docs:

At runtime, the table view stores cell objects in an internal queue. When the table view asks the data source to configure a cell object for display, the data source can access the queued object by sending a dequeueReusableCellWithIdentifier: message to the table view, passing in a reuse identifier. The data source sets the content of the cell and any special properties before returning it. This reuse of cell objects is a performance enhancement because it eliminates the overhead of cell creation.

So what you're doing when reusing cells from the queue is retrieving cells you have already created and configured. Changes made to the created Cells will be also applied to the reused cells which are displayed when scrolling as soon as the reused cells aren't visible anymore. This means you have to re-assign any values you want to override which are custom to the unique cell you are displaying, which also applies if there is no content/an empty string you want to display. Otherwise you will get random results as you have been experiencing.

let cell = tableView.dequeueReusableCellWithIdentifier("TimingsCell", forIndexPath: indexPath) as! timingCell     
let timings = self.Details!.timingsArray
let dayTime = timings[indexPath.row]
cell.dayLabel.text = dayTime.dayName

if dayTime.open != nil && dayTime.close != nil {
    cell.timeLabel.text = "\(convertTimeFormat(dayTime.open!)) - \(convertTimeFormat(dayTime.close!))"
}
else{
 //change label to empty string when reusing
 cell.timeLabel.text = "";
}

return cell

Upvotes: 5

Related Questions