Tableview cell setting keep changed when I scroll down and get back swift

I'm trying to make a table view like this image(1). When the table view cell's text get "Cancel Schedule" or "Off day" the button ">" will be grey and the cell is unable to click.

my code is work but when I scroll down and get back, the setting will mess up. the setting will randomly change like the image(2) and (3). why?

Image(1): https://www.dropbox.com/s/0k6ldrfx5nzyt9e/1.jpg?dl=0

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "rosterId", for: indexPath) as! RosterCell
        ...
        if jobCancel[indexPath.section] == 0{
            cell.separator.backgroundColor = UIColor.darkGray
            cell.jobDetail.textColor = UIColor.gray
            cell.button.isEnabled = false
            cell.button.alpha = 0.3;
        }
        if cell.jobDetail.text == "Cancelled Schedule"{
            cell.separator.backgroundColor = UIColor.red
            cell.button.isEnabled = false
            cell.button.alpha = 0.3;
            cell.isUserInteractionEnabled = false
        }
        if cell.jobDetail.text == "Off Day"{
            cell.separator.backgroundColor = UIColor.darkGray
            cell.button.isEnabled = false
            cell.button.alpha = 0.3;
            cell.isUserInteractionEnabled = false
        }

}

something like image(2) or image(3)

image(2): https://www.dropbox.com/s/jmile0vxpcqgt92/2.jpg?dl=0

image(3): https://www.dropbox.com/s/94ef4hb996afmm6/3.jpg?dl=0

1 answer

  • answered 2017-10-11 10:05 Wez

    The reason for this is cell reuse.

    It means cells that have already been styled in a certain way can be reused to display different data. You have to make sure that you setup every aspect of the styling each time a cell is reused to avoid cross over.

    It might be easier to keep track of the styling if you make a configureCell method to handle it, this way you can't forget to set one value and you could even set some default values.

    func configureCell(cell:RosterCell,
                   textColour:UIColor,
                   seperatorColour:UIColor,
                   buttonEnabled:Bool,
                   buttonAlpha:CGFloat,
                   interactionEnabled:Bool = false) {
    
            cell.separator.backgroundColor = seperatorColour
            cell.jobDetail.textColor = textColour
            cell.button.isEnabled = buttonEnabled
            cell.button.alpha = buttonAlpha
            cell.isUserInteractionEnabled = interactionEnabled
    
    }
    

    Then your cellForRowAt method would look like this

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "rosterId", for: indexPath) as! RosterCell
        ...
        if jobCancel[indexPath.section] == 0{
            configureCell(cell: cell,
                      textColour: UIColor.gray,
                      seperatorColour: UIColor.darkGray,
                      buttonEnabled: false,
                      buttonAlpha: 0.3,
                      interactionEnabled: true)
        }
        if cell.jobDetail.text == "Cancelled Schedule"{
            configureCell(cell: cell,
                      textColour: UIColor.gray,
                      seperatorColour: UIColor.red,
                      buttonEnabled: false,
                      buttonAlpha: 0.3)
        }
        if cell.jobDetail.text == "Off Day"{
            configureCell(cell: cell,
                      textColour: UIColor.gray,
                      seperatorColour: UIColor.darkGray,
                      buttonEnabled: false,
                      buttonAlpha: 0.3)
        }
    
    }
    

    As you can see I have set the interactionEnabled parameter to default to false so I did not need to set it for the last two if statements.