Reputation: 87
i looked at a couple of StackOverflow questions related with this one but it seems in not getting yet the concept very well.
I have a tableview with a couple of cells that i fill using a enum. When i scroll down the rows another row lower in the table gets selected. I have the following methods implemented:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("activityCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = activities[indexPath.item].rawValue;
return cell;
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath);
cell?.selected = true;
}
I understand that the cells are reusable but i was not able to understand properly this concept and how it applies.
Can you give me some help?
Cheers
Upvotes: 2
Views: 1794
Reputation: 735
As Byron suggested, we can handle this scenario by saving the selected index paths in an array and removing them from array when unselected.
var indexArray : [NSIndexPath]?
Initialise the indexArray before loading the table as
self.indexArray = []
Cell selection & de-selection must be reflected in the indexArray with the help of delegate functions as:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath as IndexPath) {
cell.accessoryType = .checkmark
self.indexArray?.append(indexPath as NSIndexPath)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath as IndexPath) {
cell.accessoryType = .none
if let pos = self.indexArray?.index(of: indexPath as NSIndexPath)
{
self.indexArray?.remove(at: pos)
}
}
}
Now, when cellForRowAtIndexpath function gets called for each row, check whether the current indexPath is present in our indexArray. If so, the cell is already selected, else, the cell is in unselected state & perform corresponding tasks on the cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourCellIdentifier") as! YourTableViewCell
if (self.indexArray?.contains(indexPath as NSIndexPath))!
{
cell.accessoryType = .checkmark
}
else
{
cell.accessoryType = .none
}
return cell
}
Upvotes: 0
Reputation: 37300
If you're going to reuse your cells, setting the cell as selected
in didSelectRowAtIndexPath
at indexPath in the way that you've done will make the reused cell's also reflect the changed selected
property. Instead, I'd recommend adding a boolean selected
property to your activity object such that the selection changes can be made in cellForRowAtIndexPath:
, ex:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("activityCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = activities[indexPath.item].rawValue
cell?.selected = activities[indexPath.item].selected
return cell;
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
activities[indexPath.item].selected = true
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
activities[indexPath.item].selected = false
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
Upvotes: 2