Changing image of a button in UITableViewCell on clicking it. - ios

I am developing an app in which, the image of the UIButton in UITableViewCell should change on click and I have done this in a custom cell. Right now, I am able to change the image of the button but it is also changing the image of few other buttons too as I scroll down (as cellForRowAtIndexPath: is called on scrolling).
Here is the code.
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
_cell = (ListTableViewCell *)[self.tblList dequeueReusableCellWithIdentifier:#"listTableViewCell"];
if (_cell == nil) {
_cell = [[ListTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"listTableViewCell"];
} else {
_cell.imgIcon.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#",[_arrImages objectAtIndex:indexPath.row]]];
_cell.lblList.text = [NSString stringWithFormat:#"%#",[_arrNames objectAtIndex:indexPath.row]];
_cell.btnList.tag = indexPath.row;
if (_cell.btnList.tag == indexPath.row) {
[_cell.btnList addTarget:self action:#selector(btnPressedMethodCall:) forControlEvents:UIControlEventTouchUpInside];
}
}
return _cell;
}
- (void) btnPressedMethodCall:(UIButton*)sender {
if ([sender isSelected]) {
[sender setImage:[UIImage imageNamed:#"red_image.png"] forState:UIControlStateSelected];
[sender setSelected:NO];
} else {
[sender setImage:[UIImage imageNamed:#"black_image.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
}
}
Could someone please tell how this problem can be solved. Any help is appreciated thanks.

Instead of changing image in button click event. Add selected button indexPath in NSMutableArray and in cellForRow method check NSMutableArray contain current indexPath. if yes than change button image else set normal image like below.
Swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = self.tblVW.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
cell.selectionStyle = .none
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)
if arrIndexPaths.contains(indexPath) {
cell.btn.setImage(YOUR_BUTTON_SELECTED_IMAGE, for: .normal)
}
else {
cell.btn.setImage(YOUR_BUTTON_DEFAULT_IMAGE, for: .normal)
}
cell.layoutSubviews()
return cell;
}
#IBAction func btnTapped(_ sender: UIButton) {
let selectedIndexPath = NSIndexPath.init(row: sender.tag, section: 0)
arrIndexPaths.add(selectedIndexPath)
self.tblVW.reloadData()
}
If you want to reload only single row than replace self.tblVW.reloadData() with self.tblVW.reloadRows(at: [selectedIndexPath as IndexPath], with: UITableViewRowAnimation.none)
Objective C
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil] objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.btn.tag = indexPath.row
[cell.btn addTarget:self action:#selector(btnTapped:) forControlEvents:UIControlEventTouchUpInside];
if ([arrIndexPaths containsObject: indexPath]) {
[cell.btn setImage:YOUR_BUTTON_SELECTED_IMAGE forState:UIControlStateNormal];
}
else {
[cell.btn setImage:YOUR_BUTTON_DEFAULT_IMAGE forState:UIControlStateNormal];
}
[cell layoutSubviews];
return cell;
}
-(IBAction)btnTapped:(UIButton *)sender {
NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
[arrIndexPaths addObject:selectedIndexPath];
[self.tblVW reloadData]; // Reload Whole TableView
//OR
NSArray* indexArray = [NSArray arrayWithObjects:selectedIndexPath, nil];
[self.tblVW reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationNone]; // Reload Single Row
}

Related

update array when the user updates the text field in the cell

I was wondering if there's a way to update barcodeItemsQuantity array when the user updates the text field in a custom uitableviewcell. Below are my code snippets. and I want to update data from my array whenever the user changes the textfield from the custom tableviewcell.
viewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Cell Initialized");
static NSString *cellIdentifier = #"BarcodeItemsCell";
BarcodeItemsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell == nil) {
cell = [[BarcodeItemsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell...
if (indexPath.row == [barcodeItems count]) {
// Add new row
cell.barcodeLabel.text = #"scan SKU";
cell.barcodeLabel.textColor = [UIColor lightGrayColor];
UIImage *btnImage = [UIImage imageNamed:#"barcodeIcon"];
[cell.leftButton setImage:btnImage forState:UIControlStateNormal];
cell.leftButton.tintColor = [UIColor blackColor];
cell.quantityTextField.userInteractionEnabled = NO;
[cell.leftButton addTarget:self action:#selector(scanBarcode) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"Add another Item Requested");
}
else {
// Display barcode items
cell.barcodeLabel.text = [barcodeItems objectAtIndex:indexPath.row];
UIImage *btnImage = [UIImage imageNamed:#"deleteIcon"];
cell.leftButton.tintColor = [UIColor redColor];
[cell.leftButton setImage:btnImage forState:UIControlStateNormal];
cell.leftButton.tag = indexPath.row;
[cell.leftButton addTarget:self action:#selector(deleteRow:) forControlEvents:UIControlEventTouchUpInside];
[barcodeItemsQuantity addObject:cell.quantityTextField];
}
NSLog(#"Cell Populated");
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return true;
}
-(void) deleteRow:(id)sender {
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:photoCaptureView.itemsTableView];
NSIndexPath *indexPath = [photoCaptureView.itemsTableView indexPathForRowAtPoint:buttonPosition];
[barcodeItems removeObjectAtIndex:indexPath.row];
[photoCaptureView.itemsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
NSLog(#"Item Removed");
}
barcodeitestableviewcell.h
#interface BarcodeItemsTableViewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UIButton *leftButton;
#property (strong, nonatomic) IBOutlet UILabel *barcodeLabel;
#property (strong, nonatomic) IBOutlet UITextField *quantityTextField;
#end
Yes, you can update your data model value for the textfield text placed inside custom table cell.
STEP 1:
Add delegate in your current class "UITextFieldDelegate"
class ViewController: UIViewController,UITextFieldDelegate
STEP 2:
on your "cellForRowAt indexPath" invoke the delegate to current textfield and also add the tag
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// add the following lines
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
STEP 3:
call the UITextField Delegates
func textFieldDidEndEditing(textField: UITextField) {
if !textField.text.isEmpty { // check textfield contains value or not
if textField.tag == 0 {
firstName = textField.text!
} else {
lastName = textField.text!
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField!) {
if textField.tag == 0 {
firstName = ""
} else {
lastName = ""
}
}
Here, you can replace the firstName and lastName with your desired model variables.
Hope this will work for you.

Swift 3 - Reload UICollectionView inside the UITableViewCell

I have a UICollectionView inside a UITableViewCell. You may refer the image at here
I would like to reload the collectionView if any update happen.
I have done some research and found this :
how to reload a collectionview that is inside a tableviewcell
Reloading collection view inside a table view cell happens after all cells in table view have been loaded
UICollectionView not updating inside UITableViewCell
I called the #IBOutlet weak var collectionView: UICollectionView! from UITableViewCell to UITableViewController at cellForRowAt.
Here is the code:
var refreshNow: Bool = false
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Storyboard.allCardCell, for: indexPath) as! AllCardTableViewCell
if refreshNow {
cell.collectionView.reloadData()
refreshNow = false
}
cell.collectionView.collectionViewLayout.invalidateLayout()
return cell
}
If the user click Ok on UIAlertAction :
let alert = UIAlertController(title: "Success", message: "Card successfully added", preferredStyle: .alert)
let action = UIAlertAction(title: "Ok", style: .default) { (action) in
self.refreshNow = true
self.tableView.reloadData()
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
The reason why I put the refreshNow is to prevent the apps from lagging and slow. But still did not update if any changes happen.
The problem is the collectionView did not refresh. But when I debug, it was went through the cell.collectionView.reloadData().
The update/changes only happen when I restart the apps. I want it to be so called real-times update.
Any help is really appreciated and many thanks.
Image credit: How to use StoryBoard quick build a collectionView inside UITableViewCell
At end of your update add:
DispatchQueue.main.async() { () -> Void in
self.tableView.reloadData()
}
In your case, you should assign tag to your collection view in order to get access outside the cellForRowAt function.
This is how your function should look like:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Storyboard.allCardCell, for: indexPath) as! AllCardTableViewCell
cell.collectionView.tag = 1234
return cell
}
and the action will reload it will access the collectionView by using the tag
let action = UIAlertAction(title: "Ok", style: .default) { (action) in
let collectionView = self.tableView.viewWithTag(1234) as! UICollectionView
collectionView.reloadData()
}
Also take note that cellForRowAt will keep reload the content based what you added inside it every time the cell appear. So, keep updating your data outside the cellForRowAt function.
Because you reused UITableViewCell so you must alway reload your UICollectionView. If you use refreshNow to reload UICollectionView, at the cell have refreshNow = false, UICollectionView will display like cell that it 's reused => wrong
Udate rep:
See , in picture uitableviewcell 1 will reuse at index 6. If you not reload content of cell (reload collectionview) it will display like uitableviewcell 1 at index 0
#import "AddPhotoViewController.h"
#import "PhotoTableViewCell.h"
#import "ShareTableViewCell.h"
#interface AddPhotoViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tblView;
#property (strong,nonatomic)NSMutableArray *arrImages,*arrIndexPath,*selectImages;
#end
#pragma mark - TableViewDelegate&DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *returnCell;
static NSString *cellIdentifier = #"CellOne";
static NSString *cellIdentifierTwo = #"CellTwo";
static NSString *cellIdentifierThree = #"CellThree";
if (indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
returnCell = cell;
} else if (indexPath.row == 1){
ShareTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierTwo forIndexPath:indexPath];
cell.viewMood.layer.cornerRadius = 5;
cell.viewPeople.layer.cornerRadius = 5;
[cell.viewMood layer].borderWidth = 1;
[cell.viewMood layer].borderColor = [UIColor colorWithRed:241.0/255.0 green:143.0/255.0 blue:48.0/255.0 alpha:1].CGColor;
[cell.viewPeople layer].borderWidth = 1;
[cell.viewPeople layer].borderColor = [UIColor colorWithRed:241.0/255.0 green:143.0/255.0 blue:48.0/255.0 alpha:1].CGColor;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
returnCell = cell;
}else if (indexPath.row == 2){
PhotoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierThree forIndexPath:indexPath];
cell.collView.dataSource = self;
cell.collView.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
returnCell = cell;
}
return returnCell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
#pragma mark- UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
[_arrImages addObject:chosenImage];
PhotoTableViewCell *cell = [self.tblView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
[cell.collView reloadData];
[picker dismissViewControllerAnimated:YES completion:^{
}];
}
#pragma mark - CollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [_arrImages count];
}
- ( UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"CellCollection";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *imgView = [(UIImageView*)[cell contentView] viewWithTag:100];
UIImageView *imgViewTick = [(UIImageView*)[cell contentView] viewWithTag:200];
UIView *view = [(UIView*)[cell contentView] viewWithTag:300];
if (indexPath.row == 0){
imgViewTick.hidden = YES;
view.hidden = YES;
}
if ([_arrIndexPath containsObject:indexPath]) {
[_selectImages removeAllObjects];
view.hidden = NO;
view.alpha = 0.4;
imgViewTick.hidden = NO;
imgView.image = [_arrImages objectAtIndex:indexPath.row];
[_selectImages addObject:[_arrImages objectAtIndex:indexPath.row]];
NSLog(#"Pick images:%#",_selectImages);
}else{
view.hidden = YES;
imgViewTick.hidden = YES;
imgView.image = [_arrImages objectAtIndex:indexPath.row];
}
return cell;
}

reloadRowsAtIndexPaths cannot reload index path as expected

I add a image as avatar at indexPath [0,0], and use detailLabel display nickname at indexPath [0,1].
When use reloadRowsAtIndexPaths indexPath the indexPath [0,1] get a image...
I find when invoke reloadRowsAtIndexPaths the dequeue cell return nil.
Maybe the [0,0] cell be reuse at [0,1], I don't know why so that.
The code is:
- (void)viewDidLoad {
[super viewDidLoad];
_titles = #[#"Avator", #"Nickname"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_avator = [UIImage imageNamed:#"cat"];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_nickName = #"Smallfly";
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
});
});
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _titles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *const cellIdenfier = #"cellIdentifier";
// Why reloadRowsAtIndexPaths [0,0] returned cell is nil?
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdenfier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdenfier];
}
if (indexPath.row == 0) {
[self configureCell:cell indexPath:indexPath];
} else {
NSString *nickName = _nickName ?: #"nickname";
cell.detailTextLabel.text = nickName;
}
cell.textLabel.text = _titles[indexPath.row];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
for (UIView *sv in cell.contentView.subviews) {
if ([sv isKindOfClass:[UIImageView class]]) {
[sv removeFromSuperview];
}
}
UIImage *avator = _avator ?: [UIImage imageNamed:#"user_profile_avatar"];
UIImageView *avatorImageView = [[UIImageView alloc] initWithImage:avator];
...
[cell.contentView addSubview:avatorImageView];
}
reloadRowsAtIndexPaths is a void method.
dequeueReusableCell always returns a cell (remove UITableViewCell alloc)
Objective-C
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"reuseIdentifier"
forIndexPath:indexPath];
// Configure the cell...
return cell;
}
Swift 3
open func reloadRows(at indexPaths: [IndexPath],
with animation: UITableViewRowAnimation)
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier",
for: indexPath)
// Configure the cell...
return cell
}
You may want to look at a more recent tutorial or sample code.

iOS 8 UITableViewCell Reorder Control Not Displaying

I recently upgraded my iPhone and Xcode to iOS 8 (from iOS 6) and a UITableView that was previously showing the reorder control on the UITableViewCells (in iOS 6) is no longer showing them until I press the deletion control (red circle) on the left side, at which point the "Delete" button slides over from the right side and the reorder control does appear on that particular UITableViewCell. Below are the relevant methods I am implementing in my UITableViewDataSource. I have set the editing property to YES on the UITableViewController, as well as the UITableView and UITableViewCell in viewDidLoad, but the latter two don't seem to have an effect so I removed them.
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
static NSString *CellIdentifier = #"ContactsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.editingAccessoryType = UITableViewCellAccessoryNone;
//All but the last cell should show the reorder control
if (indexPath.item < contacts.count)
{
cell.textLabel.text = [contacts contactNameAtIndex: indexPath.item];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont systemFontOfSize: 18];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.showsReorderControl = YES;
}
else
{
cell.textLabel.text = #"Add a contact";
cell.textLabel.textColor = [UIColor grayColor];
cell.textLabel.font = [UIFont systemFontOfSize: 16];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.showsReorderControl = NO;
}
return cell;
}
- (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath
{
return indexPath.item < contacts.count; //All but the last cell can be reordered
}
- (void) tableView: (UITableView *) tableView moveRowAtIndexPath: (NSIndexPath *) fromIndexPath toIndexPath: (NSIndexPath *) toIndexPath
{
[contacts moveContactAtIndex: fromIndexPath.item ToIndex: toIndexPath.item];
}
Thanks,
Vatche

How to remove the check mark on another click?

I want to make a table that user can select and deselect with a check mark:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath
{
...;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
- (void)tableView:(UITableView *) tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...;
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
...;
}
I was trying to remove the check mark when clicking on the check-marked cell again, but it takes 2 clicks to do that instead of one.
If I set selection style to default, when I click on a selected row, it removes the blue highlight; clicking again, it removes the check mark.
I also tried some conditional statements in didSelectRowAtIndexPath, but they only respond to second click as well.
What causes the problem and how do I fix it?
You can try this one:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger index = [[tableView indexPathsForVisibleRows] indexOfObject:indexPath];
if (index != NSNotFound) {
UITableViewCell *cell = [[tableView visibleCells] objectAtIndex:index];
if ([cell accessoryType] == UITableViewCellAccessoryNone) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
}
}
This should toggle the cell's checkmark on every touch.
If you additionally want only one cell to appear selected at a time, also add the following:
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger index = [[tableView indexPathsForVisibleRows] indexOfObject:indexPath];
if (index != NSNotFound) {
UITableViewCell *cell = [[tableView visibleCells] objectAtIndex:index];
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
}
If you don't want the blue hilight background, simply set the cell's selection style to UITableViewCellSelectionStyleNone once you create the cell.
Based on Starter's link to Apple docs (my code in Swift 3):
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: selectedIndexPath) {
cell.accessoryType = .none
}
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
selectedIndexPath = indexPath
}
The main point is to keep track of currently selected cell and change cell.accessoryType accordingly. Also don't forget to properly set cell.accessoryType in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) based on selectedIndexPath.
Check this Apple official doc
best solution ever
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (index != NSNotFound) {
UITableViewCell *cell = [[tableView visibleCells] objectAtIndex:index];
if (cell.accessoryType == UITableViewCellAccessoryNone)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
[self.tableName reloadData];
}
}
This helps in toggling the checkmarks (remove the check mark when clicking on the check-marked cell again)
You can use this:
You can use this:
if tableView.cellForRow(at: indexPath)?.accessoryType == .checkmark { tableView.cellForRow(at: indexPath)?.accessoryType = .none } else { tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark } tableView.deselectRow(at: indexPath, animated: true)

Resources