Uitableview Checkmark Only One Row at a Time

UITableView Checkmark ONLY ONE Row at a Time

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.

UiTableViewCell single selected checkmark for each section in the tableview

First of all, implement UITableViewDelegate's tableView(_:willSelectRowAt:) method like so,

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if let selectedIndexPathsInSection = tableView.indexPathsForSelectedRows?.filter({ $0.section == indexPath.section }), !selectedIndexPathsInSection.isEmpty {
selectedIndexPathsInSection.forEach({ tableView.deselectRow(at: $0, animated: false) })
}
return indexPath
}

Next, in both MakePaymentTableViewCell and MakePaymentTableViewCell2 cells, override setSelected(_:animated:) method, i.e.

class MakePaymentTableViewCell: UITableViewCell {
//rest of the code...
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.accessoryType = selected ? .checkmark : .none
self.checkBox.isChecked = selected
}
}

There is no need to implement didSelectRowAt and didDeselectRowAt methods.

Sample Image

Selecting TableView Cell Activates Checkmark in Rows in Multiple Sections

use data store for save checkmarks like this:

var selectedIngredients: Set<IndexPath> = [] // use set for unique save

then didSelect callBack:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
if self.selectedIngredients.contains(indexPath) {
self.selectedIngredients.remove(indexPath)

} else {
self.selectedIngredients.insert(indexPath)
}

self.tableView.reloadData()
}

after reload in CellForRow:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIngredients.contains(indexPath) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}

If you want it to have only one Row contain checkmark:

var selectedIngredients: IndexPath? = nil

and didSelect CallBack:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
self.selectedIngredients = indexPath
}

and finally:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIngredients == indexPath {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}

Set one check mark for each section in UITableView and save its state

I have found a precise and perfect solution,thanks to Lithu T.V and Nithin Gobel for guiding me in the right direction.Unfortunately their solutions didn't help me in achieving 1 check mark per section,but multiple check marks in fact.So I thought of saving the selected row in user defaults and for initially selecting 1st row of each section,we declare first and second section index,assign to index path and then assign cell accessory view as check mark.Here we go,let's first deal with cellForRowAtIndexPath:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.row,indexPath.section];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor whiteColor];
NSUserDefaults *savedState = [NSUserDefaults standardUserDefaults];

switch (indexPath.section)
{
case 0:
{
NSNumber *indexNumber = [NSNumber numberWithInteger:indexPath.row];
if([[savedState objectForKey:@"firstSectionIndex"] isEqual: indexNumber])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.firstSectionIndex = indexPath;
}

if (indexPath.row == 0)
{
NSObject * checkedCellObject = [savedState objectForKey:@"firstSectionIndex"];
if(checkedCellObject == nil)
{
self.firstSectionIndex = indexPath;
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
cell.textLabel.text = @"Yes";
}
if (indexPath.row == 1)
{
cell.textLabel.text = @"No";
}
}
break;
case 1:
{
NSNumber *indexNumber = [NSNumber numberWithInteger:indexPath.row];
if([[savedState objectForKey:@"secondSectionIndex"] isEqual: indexNumber])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
secondSectionIndex = indexPath;
}

if (indexPath.row == 0)
{
NSObject * checkedCellObject = [savedState objectForKey:@"secondSectionIndex"];
if(checkedCellObject == nil)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
secondSectionIndex = indexPath;
}
cell.textLabel.text = @"Easy";
}
if (indexPath.row == 1)
{
cell.textLabel.text = @"Medium";
}
if (indexPath.row == 2)
{
cell.textLabel.text = @"Hard";
}
}
break;

default:
break;
}
}

tableView.backgroundColor = [UIColor clearColor];
tableView.backgroundView = nil;

return cell;
}

Please observe in each case,we are checking if the checked state is in saved user defaults,if it is nil,we check 1st cell(row) of each section,here we go with table view delegate method,did select row at index path:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];

if (indexPath.section == 0)
{
UITableViewCell *checkCell = [tableView cellForRowAtIndexPath:indexPath];
if(firstSectionIndex && firstSectionIndex != indexPath)
{
UITableViewCell *uncheckCell = [tableView cellForRowAtIndexPath:firstSectionIndex];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
self.firstSectionIndex = indexPath;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:firstSectionIndex.row] forKey:@"firstSectionIndex"];
checkCell.accessoryType = UITableViewCellAccessoryCheckmark;
}

if (indexPath.section == 1)
{
UITableViewCell *checkCell = [tableView cellForRowAtIndexPath:indexPath];
if(secondSectionIndex)
{
UITableViewCell *unchekCell = [tableView cellForRowAtIndexPath:secondSectionIndex];
unchekCell.accessoryType = UITableViewCellAccessoryNone;
}
self.secondSectionIndex = indexPath;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:secondSectionIndex.row] forKey:@"secondSectionIndex"];
checkCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}

That's it,we have successfully accomplished one check mark per section and also save the accessory state of cell in user defaults for long term reference.

Hope this helps some one,thanks :)

UITableViewCell Checkmark Being Added to multiple rows when one is tapped

Maintain in your Data source which cell is to be selected.

Then in cellForRowAtIndexPath:

if (DropDownItems[indexPath.row].isSelected) {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}

and in your didSelectRowAtIndexPath Method:

if(DropDownItems[indexPath.row].isSelected) {
DropDownItems[indexPath.row].isSelected = false
} else {
DropDownItems[indexPath.row].isSelected = true
}

self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)

Multiple checkMark when row selected in UITableView IOS

[self.tableView cellForRowAtIndexPath:indexPath] call in the didSelectRowAtIndexPath will not return the exact cell. It can be same cell, new cell or reused cell. If it is a reused cell at its accessory view has a checkmark, you will end up having two cells with checkmark.

Its better to store in the array and use it accordingly. If you are planning to have multiple selections, Use the code example below.

- (void)viewDidLoad
{
[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.
self.cellSelected = [NSMutableArray array];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Cell Initialisation here

if ([self.cellSelected containsObject:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;

}
return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//if you want only one cell to be selected use a local NSIndexPath property instead of array. and use the code below
//self.selectedIndexPath = indexPath;

//the below code will allow multiple selection
if ([self.cellSelected containsObject:indexPath])
{
[self.cellSelected removeObject:indexPath];
}
else
{
[self.cellSelected addObject:indexPath];
}
[tableView reloadData];
}

UITableViewCell checkmark to be toggled on and off when tapped

Swift > 3.0

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark

}
}

I solved by using two Swift functions: the didSelectRowAtIndexPath and the didDeselectRowAtIndexPath.

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .Checkmark

}
}

To make this work properly, add a line of code to your cellForRowAtIndexPath function to select a row when the table view is drawn on the screen, otherwise the didDeselectRowAtIndexPath will not be called the first time you select another row. Like so:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellData", forIndexPath: indexPath)
if (some condition to initially checkmark a row)
cell.accessoryType = .Checkmark
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.Bottom)
} else {
cell.accessoryType = .None
}

return cell
}

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

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.

Swift: Toggling checkmark to ON for last selected cell only - not working

First tell your tableview it can only select one cell at a time:

override func viewDidLoad() {
super.viewDidLoad()

self.tableView.allowsMultipleSelection = false
}

Then, let's analyse your code, you're getting the section at which the present cell is being selected and calculating the number of rows in that specific section. You iterate on the rows of that section and checking if you have a cell at the given indexPath (I guess it always evaluates to true because you always have a cell at that indexPath, you didn't put a condition depending on the value of your for-loop). Then you tell the cell to have a checkmark if the row in the for-loop equals the row of the cell being currently selected by the user.
As your function is written, there is no reason why only the last in the section would get the checkmark, but you overcomplicated the matter.

Your cell is drawn in the following method and so should the accessory initially.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCell", for: indexPath)

cell.textLabel?.text = "your text"

cell.accessoryType = cell.isSelected ? .checkmark : .none
// cell.selectionStyle = .none if you want to avoid the cell being highlighted on selection then uncomment

return cell
}

Then you can just say that the accessory type should be .checkmark in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) and .none in tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath).Here is how to do it and you should be good, if not let me know and I can edit again.

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .checkmark
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .none
}


Related Topics



Leave a reply



Submit