0

In my application I have an multiple selection and select all option, I've tried by used below code but am facing an issue with selection.

If I press selectAll it checks and unchecks clearly and If suppose, I choose an single selection it selected but the selected cell is not higlighted.

Can you any one help me to figure out.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     return self.array.count
}

In cellForRowAtIndexPath ,

let cell = self.multipleSelectionTableview.dequeueReusableCell(withIdentifier:multiSelectionIdentifier , for: indexPath) as! MultipleSelectionCell
        if self.selectedRows.contains(indexPath){
            cell.checkBoxBtn.isSelected = true
            cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)

        } else {
            cell.checkBoxBtn.isSelected = false
            cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck"), for: .normal)
        }


        if self.multipleSelectionStatusBtn.isSelected == true {
            self.multipleSelectionStatusBtn.isSelected = true
            cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)
        } else {
            self.multipleSelectionStatusBtn.isSelected = false
            cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck"), for: .normal)
        }

        cell.checkBoxBtn.tag = indexPath.row
        return cell

In checkbox selection method,

let selectedIndexPath = IndexPath(row: sender.tag, section: 0)
        self.multipleSelectionTableview.deselectRow(at: selectedIndexPath, animated: true)
        if self.selectedRows.contains(selectedIndexPath)
        {

            self.selectedRows.remove(at: self.selectedRows.index(of: selectedIndexPath)!)
        }
        else
        {

            self.selectedRows.append(selectedIndexPath)
            print(self.selectedRows)

        }

        self.multipleSelectionTableview.reloadData()

In selectAll method,

if (sender.isSelected == true)
        {

            sender.setImage(UIImage(named: "uncheck"), for: .normal)
            sender.isSelected = false;
           // isSelecting = false
            self.selectedRows = self.getAllIndexpaths()
            self.multipleSelectionTableview.reloadData()

        }
        else
        {
           // isSelecting = true
            sender.setImage(UIImage(named: "check"), for: .normal)
            sender.isSelected = true;
            self.selectedRows = self.getAllIndexpaths()
            self.multipleSelectionTableview.reloadData()
        }

For getAllIndexPaths Method,

func getAllIndexpaths() -> [IndexPath] {
        var indexPaths: [IndexPath] = []
        for j in 0..<self.multipleSelectionTableview.numberOfRows(inSection: 0) {
            indexPaths.append(IndexPath(row: j, section: 0))
        }
        return indexPaths
    }

3 Answers3

1

You have to store selected index path in Array Like this Way you can do this easily.

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var selectedRow:[IndexPath] = []
@IBOutlet var tblView:UITableView!

override func viewDidLoad()
{
    super.viewDidLoad()
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section:
    Int) -> Int
{
    return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")

    if cell == nil
    {
        cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
    }

    cell?.textLabel?.text = String(format:"%@",indexPath.row)

    if selectedRow.contains(indexPath)
    {
        cell?.accessoryType = .checkmark
    }
    else
    {
        cell?.accessoryType = .none
    }        
    return cell!
}
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
    if selectedRow.contains(indexPath)
    {
        // For  Remove Row selection
        selectedRow.remove(at: selectedRow.index(of: indexPath)!)
    }
    else
    {
        selectedRow.append(indexPath)
    }

    tableView.reloadData()
}

// Call this method for Select All
func selectAllCall()
{
    var indexPaths: [IndexPath] = []
    for j in 0..<100
    {
        indexPaths.append(IndexPath(row: j, section: 0))
    }

    selectedRow.removeAll()

    selectedRow.append(contentsOf: indexPaths)

    tblView.reloadData()
}
}
Jignesh Mayani
  • 6,937
  • 1
  • 20
  • 36
0

Actually you are reloading data when check box is checked or unchecked. That's the reason the table view doesn't keep the selection.

Solution.

You need to keep track of the selected index paths. And in cellForRowAt: you need to check that if it is the checked index path the you need to make cell highlight by changing its background colour otherwise set cell background colour white or something else.

For eg.

//In cellForRowAtIndexPath

 if arrSelectedIndexPath.contains(indexPath) {
     // checkbox is checked, change cell bg color
 } else {
    // checkbox is not checked
 }

arrSelectedIndexPath is an [IndexPath] an array of index paths. When check box is selected you need to insert index path in an array and when check box is unchecked then you need to delete that index path from an array.

Mahendra
  • 8,448
  • 3
  • 33
  • 56
0

I am confused with your logic implementation in cellForRowAtIndexpath:

First you are checking if selectedRows array contains selected index path or not and setting the UI of checkBoxBtn:

let cell = self.multipleSelectionTableview.dequeueReusableCell(withIdentifier:multiSelectionIdentifier , for: indexPath) as! MultipleSelectionCell
if self.selectedRows.contains(indexPath){
    cell.checkBoxBtn.isSelected = true
    cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)

} else {
    cell.checkBoxBtn.isSelected = false
    cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck[enter image description here][1]"), for: .normal)
}

Then again you are checking for multipleSelectionStatusBtn and changing the UI of checkBoxBtn :

if self.multipleSelectionStatusBtn.isSelected == true {
    self.multipleSelectionStatusBtn.isSelected = true
    cell.checkBoxBtn.setImage(UIImage.init(named: "check_timesheet"), for: .normal)
} else {
    self.multipleSelectionStatusBtn.isSelected = false
    cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck_timesheet"), for: .normal)
}

cell.checkBoxBtn.tag = indexPath.row
return cell

When tableView will reload obviously this will work in multiple selection and not in single selection.

Change

In selectAll method :

if (sender.isSelected == true)
{

    sender.setImage(UIImage(named: "uncheck"), for: .normal)
    sender.isSelected = false;
   // isSelecting = false
    self.selectedRows.removeAll()
    self.multipleSelectionTableview.reloadData()

}
else
{
   // isSelecting = true
    sender.setImage(UIImage(named: "check"), for: .normal)
    sender.isSelected = true;
    self.selectedRows = self.getAllIndexpaths()
    self.multipleSelectionTableview.reloadData()
}

In cellForRowAtIndexPath :

let cell = self.multipleSelectionTableview.dequeueReusableCell(withIdentifier:multiSelectionIdentifier , for: indexPath) as! MultipleSelectionCell
if self.selectedRows.contains(indexPath){
    cell.checkBoxBtn.isSelected = true
    cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)

} else {
    cell.checkBoxBtn.isSelected = false
    cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck[enter image description here][1]"), for: .normal)
}
if getTimeSheetJSON[indexPath.row]["TaskName"].string == "" {
    cell.checkBoxBtn.isHidden = true
} else {
    cell.checkBoxBtn.isHidden = false
}

cell.checkBoxBtn.tag = indexPath.row
return cell

Hope this works as I haven't compiled your code in Xcode.

Amit
  • 4,837
  • 5
  • 31
  • 46