1

I have a music list tableView, the data on the cell are from music model. I want to change the color of the 2 labels from the default color white to red when the cell is selected. There is a property named isSelected in the music model which is used to indicates the cell is selected or not.So I use the following code:

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

        let cell = tableView.dequeueReusableCell(withIdentifier: "MusicTableViewCell", for: indexPath) as! MusicTableViewCell
        cell.music = musics[indexPath.row]
        cell.numberLabel.text = String(indexPath.row + 1)

        if musics[indexPath.row].isSelected == false {
            cell.titleLabel.textColor = .white
            cell.artistLabel.textColor = .white
            cell.speakerImageView.isHidden = true
            cell.numberLabel.isHidden = false
        } else {
            cell.titleLabel.textColor = UIColor(r: 227, g: 0, b: 24)
            cell.artistLabel.textColor = UIColor(r: 227, g: 0, b: 24)
            cell.speakerImageView.isHidden = false
            cell.numberLabel.isHidden = true
            musics[indexPath.row].isSelected = true
        }

        return cell
    }



override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

            if lastSelectedIndexPath != nil  {
            let cell = tableView.cellForRow(at: lastSelectedIndexPath)! as! MusicTableViewCell
            cell.titleLabel.textColor = .white
            cell.artistLabel.textColor = .white
            cell.speakerImageView.isHidden = true
            cell.numberLabel.isHidden = false
            musics[lastSelectedIndexPath.row].isSelected = false
        }

        let cell = tableView.cellForRow(at: indexPath) as! MusicTableViewCell
        cell.titleLabel.textColor = UIColor(r: 227, g: 0, b: 24)
        cell.artistLabel.textColor = UIColor(r: 227, g: 0, b: 24)
        cell.speakerImageView.isHidden = false
        cell.numberLabel.isHidden = true

        lastSelectedIndexPath = indexPath as IndexPath
        currentMusicIndex = indexPath.row
        musics[currentMusicIndex].isSelected = true

            }
        }

I firstly click the 2nd cell and then scroll the tableview to bottom, and click the last cell, but the app will crash.The log is: unexpectedly found nil while unwrapping an Optional value

screenshot

click the last cell

How to solve it? Thanks.

Ringo
  • 1,173
  • 1
  • 12
  • 25

3 Answers3

2

In your MusicTableViewCell class, just override isSelected property

override var isSelected: Bool{
    didSet{
        if self.isSelected
        {
            self.titleLabel.textColor = .white
            self..artistLabel.textColor = .white
            self.speakerImageView.isHidden = true
            self.numberLabel.isHidden = false

        }
        else
        {
            self.titleLabel.textColor = UIColor(r: 227, g: 0, b: 24)
            self.artistLabel.textColor = UIColor(r: 227, g: 0, b: 24)
            self.speakerImageView.isHidden = false
            self.numberLabel.isHidden = true
        }
    }
}

Now whenever, your cell is selected/de-selected, this isSelected property will customize your cell accordingly.

Edit:

To save which cell is selected, and when running the App again, you need to persist this data. There are multiple ways to persist data between multiple App sessions. You can use:

  1. UserDefaults
  2. Core Data
  3. Archive and save it in file
PGDev
  • 23,751
  • 6
  • 34
  • 88
  • 1
    Thanks, but I want to keep the status of the selected cell color when click the cell.What I mean is that when I click the cell, the musicTableviewController present another controller (assume the name is secondVC) , after the secondVC dismiss, I hope color of the cell which was clicked before is still the red. Another request is that I want to save which cell is selected, and when running the App again, the color of the last clicked cell before closing the application is still the red, while the other cells color is white. – Ringo Aug 08 '17 at 08:34
  • 1
    How to make it? Can you give some advice? I use the lastSelectedIndexPath to save the current selected indexPath, and when the application running again, in the function viewDidApper(), I will set the color of the lastSelectedIndexPath cell to red. – Ringo Aug 08 '17 at 08:35
  • 1
    yeah, I have used UserDefaults to save the lastSelectedIndexPath. – Ringo Aug 08 '17 at 10:08
2
  1. Don't use cells directly

override setSelected function in MusicTableViewCell class

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    if selected {
        self.titleLabel.textColor = UIColor(r: 227, g: 0, b: 24)
        self.artistLabel.textColor = UIColor(r: 227, g: 0, b: 24)
        self.speakerImageView.isHidden = false
        self.numberLabel.isHidden = true
    } else {
        self.titleLabel.textColor = .white
        self.artistLabel.textColor = .white
        self.speakerImageView.isHidden = true
        self.numberLabel.isHidden = false
    }
}
  1. Clear your code

override functions

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

        let cell = tableView.dequeueReusableCell(withIdentifier: "MusicTableViewCell", for: indexPath) as! MusicTableViewCell

        return cell
    }

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let _cell = cell as! MusicTableViewCell

        _cell.music = musics[indexPath.row]
        _cell.numberLabel.text = String(indexPath.row + 1)
    }

Your selection will set automatically in MusicTableViewCell.

If you should detect this.

override didSelectRowAt function

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
      print("\(indexPath)")
}
LLIAJLbHOu
  • 1,313
  • 12
  • 17
  • 1
    thanks, but I want to keep the status of the selected cell color when click the cell.What I mean is that when I click the cell, the musicTableviewController present another controller (assume the name is secondVC) , when the secondVC dismiss, I hope color of the cell which was clicked before is still the red. – Ringo Aug 08 '17 at 08:01
  • 1
    another request is that I want to save which cell is selected, and when running the App again, the color of the last clicked cell before closing the application is still the red, while the other cells color is white. How to make it? Can u give some advice? – Ringo Aug 08 '17 at 08:18
  • 1
    You can get selected indexes using self.tableView.indexPathForSelectedRow – LLIAJLbHOu Aug 08 '17 at 08:46
  • 1
    To deselect cells using https://stackoverflow.com/questions/14956823/how-to-unselect-a-uitableview-cell-when-the-user-returns-to-the-view-controller – LLIAJLbHOu Aug 08 '17 at 08:46
1

check following method to change color on select and deselect

 public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "bell" , for: indexPath)

    cell.textLabel?.text = trainingCategories[indexPath.row]
    cell.textLabel?.textColor = UIColor.white


    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.cellForRow(at: indexPath as IndexPath)?.textLabel?.textColor = UIColor.red
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tableView.cellForRow(at: indexPath as IndexPath)?.textLabel?.textColor = UIColor.white

}
iOS Geek
  • 4,825
  • 1
  • 9
  • 30