UITableView Checkmark ONLY ONE Row at a Time - ios

With this code, I can check multiple rows in a table.
But what I want is to only have one row checked at a time. Here's my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *theCell = [tableView cellForRowAtIndexPath:indexPath];
if (theCell.accessoryType == UITableViewCellAccessoryNone) {
theCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else if (theCell.accessoryType == UITableViewCellAccessoryCheckmark) {
theCell.accessoryType = UITableViewCellAccessoryNone;
}
}
If a user selects a different row, then I want the old row to simply automatically uncheck. Don't know how to do that.

Objective-C:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
Swift:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .none
}

You can create a new variable to track the index selected at didSelectRowAtIndex.
int selectedIndex;
in your cellForRowAtIndexPath
if(indexPath.row == selectedIndex)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
and in your didSelectRowAtIndex
selectedIndex = indexPath.row;
[tableView reloadData];

The best way is to set the accessory type in cellForRowAtIndexPath.
Use didSelectRowAtIndexPath to only record which path should be selected and then call reloadData.

You don't need to (and shouldn't) just reload the table after each selection.
Apple has good documentation on how to manage a selection list. See Listing 6-3 for an example.
This is more or less the same answer as some of the others but I thought I'd add a little more detail.
What you want to do is save the current selected IndexPath to a variable and use that in didSelectRowAtIndexPath to remove the old check mark. This is also where you will be adding the new check mark.
You need to make sure to also set/unset the checkmarks in cellForRowAtIndexPath otherwise if your list is large and cells are reused it will look like multiple rows are selected. This is a problem with some of the other answers.
See swift 2.0 example below:
// for saving currently seletcted index path
var selectedIndexPath: NSIndexPath? = NSIndexPath(forRow: 0, inSection: 0) // you wouldn't normally initialize it here, this is just so this code snip works
// likely you would set this during cellForRowAtIndexPath when you dequeue the cell that matches a saved user selection or the default
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// this gets rid of the grey row selection. You can add the delegate didDeselectRowAtIndexPath if you want something to happen on deselection
tableView.deselectRowAtIndexPath(indexPath, animated: true) // animated to true makes the grey fade out, set to false for it to immediately go away
// if they are selecting the same row again, there is nothing to do, just keep it checked
if indexPath == selectedIndexPath {
return
}
// toggle old one off and the new one on
let newCell = tableView.cellForRowAtIndexPath(indexPath)
if newCell?.accessoryType == UITableViewCellAccessoryType.None {
newCell?.accessoryType = UITableViewCellAccessoryType.Checkmark
}
let oldCell = tableView.cellForRowAtIndexPath(selectedIndexPath!)
if oldCell?.accessoryType == UITableViewCellAccessoryType.Checkmark {
oldCell?.accessoryType = UITableViewCellAccessoryType.None
}
selectedIndexPath = indexPath // save the selected index path
// do whatever else you need to do upon a new selection
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// if this is the currently selected indexPath, set the checkmark, otherwise remove it
if indexPath == selectedIndexPath {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
} else {
cell.accessoryType = UITableViewCellAccessoryType.None
}
}

You don't need to reload the tableView.
See the below code:
Declare a NSIndexPath lastSelectedIndexPath variable for your class
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(lastSelectedIndexPath) {
UITableViewCell *lastCell = [tableView cellForRowAtIndexPath:lastSelectedIndexPath];
[lastCell setAccessoryView:nil];
}
UITableViewCell *currentCell = [tableView cellForRowAtIndexPath:currentIndexPath];
[currentCell setAccessoryView:UITableViewCellAccessoryCheckmark];
lastSelectedIndexPath = indexPath;
}

For Swift 3 following worked for me :
override func viewDidLoad() {
super.viewDidLoad()
// allow cells to be selected
tableView.allowsSelection = true
// ensure that deselect is called on all other cells when a cell is selected
tableView.allowsMultipleSelection = false
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableVIew.cellForRow(at: indexPath as IndexPath)?.accessoryType = .checkmark
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableVIew.cellForRow(at: indexPath as IndexPath)?.accessoryType = .none
}

I think https://stackoverflow.com/a/5960016/928599 will help you.
I used it and it Works with deselectRowAtIndexPath too!

Simplest way is to save the selected IndexPath and check it in cellForRowAtIndexPath:
Initialize the selected index path:
selectedIndexPath = [[NSIndexPath alloc] init];
In cellForRowAtIndexPath:
if([selectedIndexPath isEqual:indexPath]){
[checkMark setHidden:NO];
} else {
[checkMark setHidden:YES];
}
In didSelectRowAtIndexPath:
selectedIndexPath = indexPath;
[tableView reloadData];
It should work work try this Njoy :)

Try this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.section == 1 {
// un-select the older row
if let selected = self.LastSelected {
tableView.cellForRowAtIndexPath(selected)?.accessoryType = .None
}
// select the new row
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
self.LastSelected = indexPath
}
}

In Swift, following works perfectly:
lastSelectedIndexPath = NSIndexPath(forRow: 1, inSection: 0)//Row will be the previous selected row
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell:LabelsSelectionCell = tableView.dequeueReusableCellWithIdentifier("LabelsSelectionCell", forIndexPath: indexPath) as! LabelsSelectionCell
cell.setCellLael(labelOptionsArray[indexPath.row])
if lastSelectedIndexPath == indexPath
{
cell.setCellCheckedStatus(true)
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if let _ = lastSelectedIndexPath
{
let lastCell:LabelsSelectionCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath!) as! LabelsSelectionCell
lastCell.setCellCheckedStatus(false)
}
let currentCell:LabelsSelectionCell = tableView.cellForRowAtIndexPath(indexPath) as! LabelsSelectionCell
currentCell.setCellCheckedStatus(true)
lastSelectedIndexPath = indexPath
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

In Swift 2.0 I used this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if((lastSelectedIndexPath) != nil) {
let lastCell = tableView.cellForRowAtIndexPath(lastSelectedIndexPath)
lastCell?.accessoryType = UITableViewCellAccessoryType.None
}
let currentCell = tableView.cellForRowAtIndexPath(indexPath)
currentCell?.accessoryType = UITableViewCellAccessoryType.Checkmark
lastSelectedIndexPath = indexPath
}

My way is deselect other cells during selecting:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ....
if condition {
cell.accessoryType = .checkmark
tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.bottom)
} else {
cell.accessoryType = .none
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
for row in 0...tableView.numberOfRows(inSection: 0) {
if row == indexPath.row {continue}
tableView.deselectRow(at: IndexPath(row: row, section: 0), animated: true)
}
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryType = .none
}

Here's what I came up when I had this problem.
This code is implemented in the latest version of Swift, as of today...
For more info and/or the extension file, please check out the Github Gist of this snippet.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let sip = selectedIndex {
tableView.deselectRow(at: sip, animated: false)
}
selectedIndex = indexPath
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if selectedIndex?.row == indexPath.row {
selectedIndex = nil
}
}

tested and solved try this its worked perfectly
add this as global variable
var selectedIndexPath = NSIndexPath(row: 0, section: 0)
Add this in didselect method
// old one check off
if indexPath != selectedIndexPath as IndexPath {
let oldCell = categorytable.cellForRow(at: selectedIndexPath as IndexPath)
if oldCell?.accessoryView != nil {
oldCell?.accessoryView = nil
}
else {
let imageName = "checkmark"
let image: UIImageView = UIImageView(image: UIImage(named: imageName))
cell.accessoryView = image
}
}
// the new one on
if cell.accessoryView == nil {
let imageName = "checkmark"
let image: UIImageView = UIImageView(image: UIImage(named: imageName))
cell.accessoryView = image
}
else {
cell.accessoryView = nil
}

You can do it in custom cell type in one line of code.
final class CheckableTableViewCell: UITableViewCell {
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.accessoryType = selected ? .checkmark : .none
}
}
To make this method work - your cell should be selected.
If you don’t want to see the highlight of the selected cell, just set cell's selectionStyle to .none in storyboard or in code
This method will not work, if you will call
tableView.deselectRow(at: indexPath, animated: true)
Also works great with multiple selection.

Swift 5 version of jeffjv's response.
// for saving currently selected index path
var selectedIndexPath: NSIndexPath? = NSIndexPath(forRow: 0, inSection: 0) // you wouldn't normally initialize it here, this is just so this code snip works
// likely you would set this during cellForRowAtIndexPath when you dequeue the cell that matches a saved user selection or the default
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
// this gets rid of the grey row selection. You can add the delegate didDeselectRowAtIndexPath if you want something to happen on deselection
tableView.deselectRow(at: indexPath, animated: true) // animated to true makes the grey fade out, set to false for it to immediately go away
// if they are selecting the same row again, there is nothing to do, just keep it checked
if indexPath == selectedIndexPath! as IndexPath {
return
}
// toggle old one off and the new one on
let newCell = tableView.cellForRow(at: indexPath)
if newCell?.accessoryType == UITableViewCell.AccessoryType.None {
newCell?.accessoryType = UITableViewCell.AccessoryType.Checkmark
}
let oldCell = tableView.cellForRow(at: selectedIndexPath! as IndexPath)
if oldCell?.accessoryType == UITableViewCell.AccessoryType.Checkmark {
oldCell?.accessoryType = UITableViewCell.AccessoryType.None
}
selectedIndexPath = indexPath as NSIndexPath // save the selected index path
// do whatever else you need to do upon a new selection
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// if this is the currently selected indexPath, set the checkmark, otherwise remove it
if indexPath == selectedIndexPath! as IndexPath {
cell.accessoryType = UITableView.CellAccessoryType.Checkmark
} else {
cell.accessoryType = UITableView.CellAccessoryType.None
}
}

Swift iOS
var checkedIndexPath : NSIndexPath?
// table row which row was selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
println("Section #\(indexPath.section)! You selected cell #\(indexPath.row)!")
if (self.checkedIndexPath != nil) {
var cell = tableView.cellForRowAtIndexPath(self.checkedIndexPath!)
cell?.accessoryType = .None
}
var cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.accessoryType = .Checkmark
self.checkedIndexPath = indexPath
}// end tableView

Store the selected index path, update it in didSelectRowAt:, and from there call reloadRows(at: to reload only the old and new checked rows (not the entire table view):
var selectedIndexPath: IndexPath?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let previous = selectedIndexPath
selectedIndexPath = indexPath
let allowDeselection = true // optional behavior
if allowDeselection && previous == selectedIndexPath {
selectedIndexPath = nil
}
tableView.reloadRows(at: [previous, selectedIndexPath].compactMap({ $0 }), with: .automatic)
tableView.deselectRow(at: indexPath, animated: true)
}
Handle the setting of the checkmark accessory view in cellForRowAt indexPath:. This will account for cell reuse and also be triggered by your above calls to reloadRows(at:, avoiding duplicating the code of setting the cell accessory:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "IDENTIFIER", for: indexPath)
cell.accessoryType = (indexPath == selectedIndexPath) ? .checkmark : .none
// ...
return cell
}

Related

Disclosure indicator to specific cell in static TableView in Swift

I created a static TableView and I would like to add or remove a disclosure indicator depending if we are consulting our own account or a guest account.
This is what I would like :
let index = IndexPath(row: 4, section: 0)
let cell = tableView.cellForRow(at: index)
if currentUser {
cell.accessoryType = .none
//cell.backgroundColor = UIColor.red
}
I tried to put it in the viewDidLoad function but it didn't work. I tried cellForRowAt indexPath also and same result.
How could I do that?
Just check if you want to show disclosure indicator in cellForRowAt indexPath method.
if (wantsToShow){ // Your condition goes here
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
}
else{
cell.accessoryType = .none
}
That's it.
Your are working with static cells so cellForRow will not get called. Instead, simply drag connect your cell and set it up, like this
Please use below code in cellForRowTableView code
It will work for you
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
if currentUser {
// Own Account
cell.accessoryType = .none
//cell.backgroundColor = UIColor.red
}else{
//Guest Account
cell.accessoryType =.checkmark
}
}
Swift
Specific cell
if indexPath.row == 1 {
cell.accessoryType = .disclosureIndicator
} else {
cell.accessoryType = .none
}
To add accessory on a specific static cell, I used tableView, cellForRowAt but i couldn't access a reference to UITableViewCell.
Then i found super.tableView(tableView, cellForRowAt: indexPath)
So here is my code:
Assuming you know the specific indexpath you want:
var indexPathSort = IndexPath(item: 0, section: 0)
var indexPathPrice = IndexPath(item: 0, section: 1)
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if indexPath == indexPathSort || indexPath == indexPathPrice {
cell.accessoryType = .checkmark
}
return cell
}

Swift : Save & Show selected indexPath in static Table View

I have a little problem with my static tableview. I have a PopOver which is shown as an option for my grid. I want to save the state(indexPath) of my static TableView but seems it doesnt work, below is my snippet code :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var currSelected: IndexPath?
let section = indexPath.section
let numberOfRows = tableView.numberOfRows(inSection: section)
for row in 0..<numberOfRows {
if let cell = tableView.cellForRow(at: NSIndexPath(row: row, section: section) as IndexPath) {
cell.accessoryType = row == indexPath.row ? .checkmark : .none
tableView.deselectRow(at: indexPath, animated: false)
currSelected = indexPath
if section == 2 {
tableView.deselectRow(at: indexPath, animated: false)
cell.accessoryType = .none
}
else {
delegate?.option(lastSelected: currSelected!)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reload"), object: nil)
}
}
}
}
I'm trying to use delegate to throw the lastSelected (last indexPath) to previous controller and send it back to the Pop Over Controller and i got it. But i dont know to show the checkmark using this lastSelected. And the prepare for cell at function need a identifier for a reused cell but i dont use it.
I have read this for showing the checkmark but its not saving the state. I have read this too but its same too. Any suggestions/answer will help for me. Thanks in Advance
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath == lastSelected {
cell.accessoryType = .Checkmark
}
}

UITableviewCell toggling only one custom checkmark state not working - Swift 3

I have reviewed this link and the solutions were not working for me.
I am trying to select one row and when I do select it, it adds a checkmark to the label. If another row is selected while there is an existing checkmark, it will uncheck the previous one which is stored in a selectedIndexPath variable.
It works in the beginning, however when scrolling through the tableview several times, I occasionally see a cell selected that should not be as indicated in this image:
What I am doing when a user selects a cell:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? CustomCell {
let customCell = customCellData[indexPath.row]
customCell.toggleSelected()
cell.configureCheckmark(with: customCell)
}
if let oldIndexPath = selectedIndexPath, let cell = tableView.cellForRow(at: oldIndexPath) as? CustomCell, oldIndexPath.row != indexPath.row {
let customCell = customCellData[oldIndexPath.row]
customCell.toggleSelected()
cell.configureCheckmark(with: customCell)
}
if let selected = selectedIndexPath, selected.row == indexPath.row {
selectedIndexPath = nil
tableView.deselectRow(at: indexPath, animated: true)
} else {
selectedIndexPath = indexPath
}
}
and in for cellForRowAt: (is it redundant to check the selectedIndexPath and the state in the model?)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
let customCell = customCellData[indexPath.row]
cell.customCell = customCell
if selectedIndexPath == indexPath {
cell.checkLabel.text = "✔️"
} else {
cell.checkLabel.text = ""
}
return cell
}
and finally in the CustomCell:
var customCell: CustomCell? {
didSet {
if let customCell = customCell {
configureCheckmark(with: customCell)
}
}
}
func configureCheckmark(with customCell: CustomCellData) {
if customCell.isSelected {
checkLabel.text = "✔️"
} else {
checkLabel.text = ""
}
}
In CustomCellData I toggle the state as follows:
class CustomCellData {
var isSelected = false
func toggleSelected() {
isSelected = !isSelected
}
}
I am scratching my head on this and unsure what to do, any help would be great.
The easiest solution is to reduce didSelectRowAt to
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
selectedIndexPath = indexPath
tableView.reloadData()
}
This updates all visible cells properly.
Or more sophisticated version which updates only the affected rows and checks if the cell is already selected
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if selectedIndexPath != indexPath {
let indexPathsToReload = selectedIndexPath == nil ? [indexPath] : [selectedIndexPath!, indexPath]
selectedIndexPath = indexPath
tableView.reloadRows(at: indexPathsToReload, with: .none)
} else {
selectedIndexPath = nil
tableView.reloadRows(at: [indexPath], with: .none)
}
}
The code in cellForRowAt does the rest.

indexPathForSelectedRow returns nil although I have a cell programmatically selected

I have a UITableView which I load with some application settings. I need the table to be single-select, and since the table holds settings there might be a chance some cell will be programmatically selected based on the setting enabled status.
Currently, I'm experiencing a weird behaviour where if I programmatically select a cell then indexPathForSelectedRow returns nil (when it should return the index for the cell I selected), thus when I tap on a second cell (to change the currenty selected setting) I end up with two cells selected (even when I set allowMultipleSelection to false in my tableView object).
Here's my code:
override func viewDidLoad() {
tableView.allowsMultipleSelection = false
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("myCell")
if let cell = cell {
// tableObject is an array containing settings model
let row = tableObject[indexPath.row]
cell.textLabel!.text = row.settingValue
if row.selected {
cell.setSelected(true, animated: false)
cell.accessoryType = .Checkmark
}
cell.tag = row.id
}
return cell!
}
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
// oldIndex is always nil for the cell I called setSelected in cellForRowAtIndexPath
if let oldIndex = tableView.indexPathForSelectedRow {
if let oldCell = tableView.cellForRowAtIndexPath(oldIndex) {
tableView.deselectRowAtIndexPath(oldIndex, animated: true)
oldCell.accessoryType = .None
}
}
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.setSelected(true, animated: true)
cell.accessoryType = .Checkmark
}
return indexPath
}
override func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
return indexPath
}
Any idea how I can always have only one cell selected at a time?
Thanks!
Just in case someone else comes across this same behaviour, it seems that selecting the cell through cell.setSelected() it's not the same as invoking tableView.selectRowAtIndexPath() method. Selecting the row with the latest does the job perfectly and solves the issue.
Note that calling tableView.reloadData() resets the tableView.indexPathForSelectedRow to nil.
here how you can accomplish table view single selection through tableView.indexPathForSelectedRow :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.accessoryType = tableView.indexPathForSelectedRow == indexPath ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if let visiblePaths = tableView.indexPathsForVisibleRows
{
for visibleIndexPath in visiblePaths
{
let cell = tableView.cellForRow(at: visibleIndexPath)
if visibleIndexPath == indexPath
{
cell?.accessoryType = .checkmark
}
else
{
cell?.accessoryType = .none
}
}
}
}
Create an array like
var arrSelectCell = [NSIndexPath]()
And do the code at didSelectRowAtIndexPath like following:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if arrSelectCell.contains(indexPath) {
if let oldCell = tableView.cellForRowAtIndexPath(indexPath) {
if let index = arrSelectCell.indexOf(indexPath) {
arrSelectCell.removeAtIndex(index)
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
oldCell.accessoryType = .None
}
}
else
{
arrSelectCell.append(indexPath)
if let selectCell = tableView.cellForRowAtIndexPath(indexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
selectCell.accessoryType = .Checkmark
}
}
and also dont forget to set a code in cellForRowAtIndexPath to check already checked and unchecked cell maintain after reuse cell also. So need to few code you need to write as following.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("serchCell", forIndexPath: indexPath) as! SearchTableViewCell
if arrSelectCell.contains(indexPath)
{
cell.accessoryType = .Checkmark
}
else
{
cell.accessoryType = .None
}
return cell
}

UI table view cell check marks repeating swift

My when a table cell is checked and you scroll down a check mark is repeated.
I know this is due to cell reuse, but don't know how to fix it.
function to populate table
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let item = self.myEvents[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("row", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = self.myEvents[indexPath.row]
return cell
}
//function to make the table checkable
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("indexpath: \(indexPath)")
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
let text = cell.textLabel!.text
if cell.accessoryType == UITableViewCellAccessoryType.None {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
//let text = cell.textLabel!.text
if(checkedEvents[0] == ""){
checkedEvents[0] = text!
}else{
checkedEvents.append(text!)
}
} else {
cell.accessoryType = UITableViewCellAccessoryType.None
var index = 0
for event in checkedEvents{
if event == text{
self.checkedEvents.removeAtIndex(index)
index++
}
}
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
First, you need to store the number of the selected row somewhere. How about self.selectedRowNumber?
var selectedRowNumber: Int? = nil
Set this when the user selects a row (short version):
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
cell.accessoryType = .Checkmark
self.selectedRowNumber = indexPath.row
// You'll also need some code here to loop through all the other visible cells and remove the checkmark from any cells that aren't this one.
}
Now modify your -tableView:cellForRowAtIndexPath: method to clear the accessory if it's not the selected row, or add it if it is:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("row", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = self.myEvents[indexPath.row]
cell.accessoryType = .None
if let selectedRowNumber = self.selectedRowNumber {
if indexPath.row == selectedRowNumber {
cell.accessoryType = .Checkmark
}
}
return cell
}
This code was written here in the browser, and may need some fixes to compile.
If you want only one selection, put tableView.reloadData() in your didSelectRowAtIndexPath function

Resources