I am showing pincodes in tableview, and when i select a cell then it should select and if i tap on the same cell again then it should deselect(while tapping cell should work like switch)
but with below code
issue 1: initially i am unable to select 1st row but after selecting any other row and then able to select 1st row.. why? where am i wrong?
issue 2: only one time i can select deselect the same row with two tapping if i tap 3rd time continuously then unable to select the same row, why?.. please guide
class PincodeModel{
var name: String?
var id: Int?
var isSelected: Bool
init(name: String?, id: Int?, isSelected: Bool) {
self.name = name
self.id = id
self.isSelected = isSelected
}
}
class FilterViewController: UIViewController {
var pincodePreviousIndex: Int = -1
var pincodes = [PincodeModel]()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
for pincode in pincodeList {
self.pincodes.append(PincodeModel(name: pincode, id: 0, isSelected: false))
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubFilterTableViewCell", for: indexPath) as! SubFilterTableViewCell
cell.title.text = self.pincodes[indexPath.row].name
if !self.pincodes.isEmpty {
if self.pincodes[indexPath.row].isSelected == true {
cell.tickImageView.image = #imageLiteral(resourceName: "iconTick")
}else {
cell.tickImageView.image = UIImage()
}
}
return cell
}
// EDITED Code according to below answer
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.pincodes[indexPath.row].isSelected = !self.pincodes[indexPath.row].isSelected
if self.pincodes[indexPath.row].isSelected == true {
self.filterData.pincode = pincodes[indexPath.row].name ?? ""
}else {
self.filterData.pincode = ""
}
if pincodePreviousIndex > 0 && pincodePreviousIndex != indexPath.row {
pincodes[pincodePreviousIndex].isSelected = false
}
pincodePreviousIndex = indexPath.row
}
this is working as i want when i select from index = 1, but if i select first row(index = 0) then the right mark remains if i select another row, why?
o/p with edited code:
2
Answers
For issue 1 – By using this line of code:
var pincodePreviousIndex: Int = 0
You cannot click the first row until you click another since
pincodes[pincodePreviousIndex].isSelected = false
Since you’re defaulting to 0 in the beginning, that correlates to the first row.
For issue 2 – if you select row 2 (selected) and then select it again to deselect it: pincodePreviousIndex will hold the value of that row and then deselect it again with
pincodes[pincodePreviousIndex].isSelected = false
So even though you’re selecting it it will deselect it.
I would do this at the top:
var pincodePreviousIndex: Int = -1
and at the bottom:
There are a couple approaches you can take to save yourself some trouble.
First, set
.selectionStyle = .none
on your cells, and then in your cell class, overridesetSelected(...)
. For example, I added an image view to my cell and gave it an empty-box as its image, and a checked-box as its highlighted image:Now the cell appearance will reflect its selected state which is maintained by the table view.
Next, instead of
didSelectRowAt
, we’ll implementwillSelectRowAt
… if the cell is currently selected, we’ll deselect it (and update our data):Here’s a complete example:
It will look like this:
When running:
Note that if a selected row is scrolled out-of-view, it will remain selected (and will show selected when scrolled back into view) and the data and table view selection states will continue to be correct.
Edit
If we want to use
didSelectRowAt
(perhaps for other uses), we can "toggle" the selected row like this: