3

I have a table view. I am using multiple cell selection. Everything is working correctly, functionality wise, but UI wise it is not. Whenever I select a cell and scroll down I see the color is changed in another cell below though that cell was never actually selected. What I have done is this for the cell:

class FollowSportsCell: UITableViewCell {

@IBOutlet weak var sportL: UILabel!
@IBOutlet weak var backImg: UIImageView!

override func awakeFromNib() {

    super.awakeFromNib()
}

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

    super.setSelected(selected, animated: animated) 
}

override func prepareForReuse() {

    super.prepareForReuse()

    backImg.backgroundColor = UIColor(hexString: "E6E6E6")

    sportL.textColor = .black


}

And, here are delegates.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return sportsArr!.count

}

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

    let cell                   = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as!                                                                         FollowSportsCell

    let sport                 = sportsArr![indexPath.row]["id"] as! Int

    cell.sportL.text      = sportsArr![indexPath.row]["title"] as? String

    cell.selectionStyle = UITableViewCell.SelectionStyle.none

    if selectedSports.contains(sport) {

        cell.sportL.textColor = .white

        cell.backImg.backgroundColor = UIColor(hexString: "4293CC")

    }

    return cell

}

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

    selectedCell += 1

    let sport = sportsArr![indexPath.row]["id"]

    selectedSports.append(sport! as! Int)

    if selectedCell > 1
    {
        collectionB[0].backgroundColor = UIColor(hexString: "4293CC")

        collectionB[0].isEnabled               = true
    }

}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {

    selectedCell -=  1

    selectedSports = selectedSports.filter{$0 != sportsArr![indexPath.row]["id"] as! Int}

    if selectedCell < 2
    {
        collectionB[0].backgroundColor = .lightGray

        collectionB[0].isEnabled               =  false
    }

}

When, the number is low like 4 or 5 and the scroll doesn't appear everything is good, but once they are like 20-22 then, I get this issue. Any help?

Rob13
  • 381
  • 8
  • 20
  • it's happen due to reusable cell? – V D Purohit Oct 30 '18 at 06:49
  • @VDPurohit Yes, I am 100% sure. – Rob13 Oct 30 '18 at 06:52
  • You need to understand the reusing concept. If you are making any change to a cell, it will stay like that only unless you invert it. So you need to keep track which one is selected and use if else condition to set the color otherwise. – Sharad Chauhan Oct 30 '18 at 06:52
  • As mentioned above you need to understand reusable concept first. Also look into following similar answer may helps to solve. https://stackoverflow.com/questions/52753084/textlabel-colour-automatically-changed-when-i-scroll-uitableview/52753623#52753623. – Abdul Rehman Oct 30 '18 at 07:28

3 Answers3

3

You should handle background color in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) . Check and use below code. Hope it will work

 var selectedCells = Array<NSInteger>()

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return sportsArr!.count

}

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

    let cell             = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! FollowSportsCell

    cell.sportL.text     = sportsArr![indexPath.row]["title"] as? String

    cell.selectionStyle  = UITableViewCell.SelectionStyle.none

    if self.selectedCells.contains(indexPath.row) {
        cell.sportL.textColor = .white

        cell.backImg.backgroundColor = UIColor(hexString: "4293CC")

        if self.selectedCells.count > 1
        {
            collectionB[0].backgroundColor = UIColor(hexString: "4293CC")

            collectionB[0].isEnabled               = true
        }
    }
    else
    {
        //Here Set your default color for cell backImgr background color
        cell.sportL.textColor = // set default color

            cell.backImg.backgroundColor = // set default color

    }
    return cell

}

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

    let cell = tableView.cellForRow(at: indexPath) as! FollowSportsCell

    if self.selectedCells.contains(indexPath.row) {
        //Here you will get selected cell and going to deselect...Do anything with deselection

        if let index = self.selectedCells.index{$0 == indexPath.row}
        {
          self.selectedCells.remove(at: index)
        }

        cell.sportL.textColor = .black

        cell.backImg.backgroundColor = UIColor(hexString: "E6E6E6")

        selectedCell -=  1

        selectedSports = selectedSports.filter{$0 != sportsArr![indexPath.row]["id"] as! Int}

        if self.selectedCells.count < 2
        {
            collectionB[0].backgroundColor = .lightGray

            collectionB[0].isEnabled               =  false
        }

    }
    else
    {
        self.selectedCells.append(indexPath.row)
        print(cell.sportL.text!)

        selectedCell += 1

        let sport = sportsArr![indexPath.row]["id"]

        selectedSports.append(sport! as! Int)
    }

    self.yourtblView.reloadData()



}
Rakesh Patel
  • 1,673
  • 10
  • 27
  • Kind of doing the same, but the color is not changing immediately I have to scroll up and down and then it changes, kind of freezes. – Rob13 Oct 30 '18 at 07:12
  • Just reload table in didSelect method. – Rakesh Patel Oct 30 '18 at 07:13
  • Don't you think if I will reload the table everytime, I will be able to select the selected cell already. – Rob13 Oct 30 '18 at 07:18
  • Using selecetedcells array you can manage everything in didSelect..no need to keep cell in selected state – Rakesh Patel Oct 30 '18 at 07:20
  • Ok, I have done your way it works, but now for `didDeselectRow` the colors are not changing. Any help regarding that? – Rob13 Oct 30 '18 at 07:22
  • One minute..I Edit my answered...I 'll all managed in DidSelect – Rakesh Patel Oct 30 '18 at 07:23
  • Checking now. Please wait, – Rob13 Oct 30 '18 at 07:37
  • No return here: `let index = self.selectedCells.contains { (indx) -> Bool in if indx == indexPath.row { self.selectedCells.remove(at: indx) } }` and where are we using `index`? – Rob13 Oct 30 '18 at 07:43
  • It selects the cell and change the color, but when I try to select it in order to deselect it the color didn't change and it gave an error `Fatal: Index out of range` – Rob13 Oct 30 '18 at 07:51
  • Yeah, it works now. But, can we do the same with `didSelect` and `didDeselect`? – Rob13 Oct 30 '18 at 08:11
  • Yes it is possible but you have to manage this selection array in both methods and cell related changes handle in cellForRowAtIndexpath method using this selection array. – Rakesh Patel Oct 30 '18 at 08:21
  • Oh! Okay. Thanks for your help. – Rob13 Oct 30 '18 at 08:21
  • Do you know any way that I can select only the elements within the cell and not the entire cell? – Rob13 Oct 30 '18 at 09:32
  • i did't get your question..can you explain more? – Rakesh Patel Oct 30 '18 at 09:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182777/discussion-between-rob13-and-rakesh-patel). – Rob13 Oct 30 '18 at 09:49
0

Please select your default and selected color in "CellForRowAtIndexPAth". Please check the below code.

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

    let cell             = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! FollowSportsCell
    cell.sportL.text     = sportsArr![indexPath.row]["title"] as? String
    cell.selectionStyle  = UITableViewCell.SelectionStyle.none

    let sport = sportsArr![indexPath.row]["id"]
    cell.sportL.textColor = default cell colour
    cell.backImg.backgroundColor = default cell colour


    if selectedSports.contain(sport) {
            cell.sportL.textColor = required cell colour
            cell.backImg.backgroundColor = required cell colour

    }
    return cell

    }
Myaaoonn
  • 1,001
  • 12
  • 25
0
import UIKit

class TableVC: UIViewController,UITableViewDelegate,UITableViewDataSource {

    @IBOutlet weak var tableView : UITableView!

   var arrayOfTitle : [titleOfArray] = [titleOfArray]()

   override func viewDidLoad() {
        super.viewDidLoad()

        if self.tableView != nil {
            self.tableView.delegate = self
            self.tableView.dataSource = self
        }

        for i in 0...20 {
            self.arrayOfTitle.append(titleOfArray(title: "Test\(i)", isSelectedIndex: false))
        }

        // Do any additional setup after loading the view.
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return 80
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return self.arrayOfTitle.count
    }

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

        let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")
        cell?.textLabel!.text = self.arrayOfTitle[indexPath.row].title
        cell?.textLabel!.textColor =  self.arrayOfTitle[indexPath.row].isSelectedIndex ? UIColor.red : UIColor.blue
        return cell!
    }

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

        for i in 0...self.arrayOfTitle.count-1 {
            self.arrayOfTitle[i].isSelectedIndex = false
        }
        self.arrayOfTitle[indexPath.row].isSelectedIndex = true
        tableView.reloadData()
    }
}


class titleOfArray : NSObject {

    var title : String!
    var isSelectedIndex : Bool!

    init(title:String! ,isSelectedIndex :Bool) {

        self.title = title
        self.isSelectedIndex = isSelectedIndex
    }
}

this might be helpful

V D Purohit
  • 1,179
  • 1
  • 10
  • 23