Reputation: 4343
I am using table view for selecting objects. I want to select muliple objects in a tableview. I am using following code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: ContactCell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier) as! ContactCell
let row = indexPath.row
let person=contacts[row]
cell.setCell(person.nameLabel,image: "")
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let row = indexPath.row
let person=contacts[row]
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if cell.accessoryType == .Checkmark
{
cell.accessoryType = .None
}
else
{
cell.accessoryType = .Checkmark
}
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
My tableview looks like this:
I selected the "Kate" then I scroll down to bottom and "Test" is marked too. But why? I selected just "Kate". How can I prevent this?
Upvotes: 0
Views: 610
Reputation: 1967
It is selected "too", because inside a UITableView cells are reused...
let cell: ContactCell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier) as! ContactCell
If you want to solve this problem, the best way would be to save each cells state inside the array, which is holding your data of the UITableView... This is the best way.
Another way would be to declare a Dictionary of type [Int: Bool] and save your selected states to this... the Int key would be the row index, and its value could be true for selected, or false for not...
UPDATE
Following an example on how to solve your problem
class CustomTableViewController: UITableViewController {
@IBOutlet weak var contactsTableView: UITableView!
lazy var contactsArray: [[String: AnyObject]] = [[String: AnyObject]]()
//This method is to convert your contacts string array, into the array you need
private func appendContactsToContactsArray (contacts: [String]) {
for contact in contacts {
contactsArray.append(["name": contact, "selected": false])
}
contactsTableView.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contactsArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: ContactCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! ContactCell
cell.textLabel?.text = contactsArray[indexPath.row]["name"] as? String
if (isCellSelectedAtIndexPath(indexPath)) {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
} else {
cell.accessoryType = UITableViewCellAccessoryType.None
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (isCellSelectedAtIndexPath(indexPath)) {
contactsArray[indexPath.row]["selected"] = false
} else {
contactsArray[indexPath.row]["selected"] = true
}
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
private func isCellSelectedAtIndexPath (indexPath: NSIndexPath) -> Bool {
return contactsArray[indexPath.row]["selected"] as? Bool ?? false
}
}
Upvotes: 1
Reputation: 31016
You're seeing this effect because cells are cached and reused. Note the word "Reusable" in dequeueReusableCellWithIdentifier
.
Make "selected" a property of a contact or person. Set it true or false when a row is selected or deselected. Reload your data and set the accessory type in cellForRowAtIndexPath
.
Upvotes: 0