[ios] How to deselect a selected UITableView cell?

I am working on a project on which I have to preselect a particular cell.

I can preselect a cell using -willDisplayCell, but I can't deselect it when the user clicks on any other cell.

- (void)tableView:(UITableView*)tableView 
        willDisplayCell:(UITableViewCell*)cell
        forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        [cell setSelected:YES];    
    } 
}

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;
    [materialTable deselectRowAtIndexPath:indexpath1 animated:NO];
}

Can you help?

The answer is


What I've found is that on top of setting the cell as selected, you have to let the table view know to select the row at the given index path.

// Swift 3+  

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if appDelegate.indexPathDelegate.row == indexPath.row {
        self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        cell.setSelected(true, animated: true)
    }
}

NSIndexPath * index = [self.menuTableView indexPathForSelectedRow];
[self.menuTableView deselectRowAtIndexPath:index animated:NO];

place this code according to your code and you will get your cell deselected.


try this

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

To have deselect (DidDeselectRowAt) fire when clicked the first time because of preloaded data; you need inform the tableView that the row is already selected to begin with, so that an initial click then deselects the row:

//Swift 3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if tableView[indexPath.row] == "data value"

        tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)

    }
}

Please check with the delegate method whether it is correct or not. For example;

-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

for

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

Swift 4:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let cell = tableView.cellForRow(at: indexPath)
    if cell?.isSelected == true { // check if cell has been previously selected
        tableView.deselectRow(at: indexPath, animated: true)
        return nil
    } else {
        return indexPath
    }
}

Swift 4:

tableView.deselectRow(at: indexPath, animated: true)

Based on saikirans solution, I have written this, which helped me. On the .m file:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        selectedRowIndex = nil;

    }

    else {  self.selectedRowIndex = [indexPath retain];   }

    [tableView beginUpdates];
    [tableView endUpdates];

}

And on the header file:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

I am not very experienced either, so double check for memory leaks etc.


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

If you want to select any table cell with the first click and deselect with the second, you should use this code:

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath {   

    if (self.selectedIndexPath && 
        [indexPath compare:self.selectedIndexPath] == NSOrderedSame) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
         self.selectedIndexPath = nil;
    } 
    else {
        self.selectedIndexPath = indexPath;
    }
}

Swift 3.0:

Following the protocol conformance section of the ray wenderlich swift style guide, to keep related methods grouped together, put this extension below your view controller class like that:

// your view controller
class MyViewcontroller: UIViewController {
  // class stuff here
}

// MARK: - UITableViewDelegate
extension MyViewcontroller: UITableViewDelegate {
      // use the UITableViewDelegate method tableView(_:didSelectRowAt:)
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // your code when user select row at indexPath

        // at the end use deselectRow
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

Swift 3/4

In ViewController:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

In Custom Cell:

override func awakeFromNib() {
    super.awakeFromNib()
    selectionStyle = .none
}

Can you try this?

- (void)tableView:(UITableView *)tableView 
  didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    AppDelegate_iPad *appDelegte = 
    (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];
    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;

    UITableViewCell *prevSelectedCell = [tableView cellForRowAtIndexPath: indexpath1];
    if([prevSelectedCell isSelected]){
       [prevSelectedCell setSelected:NO];
    }
}

It worked for me.


swift 3.0

    tableView.deselectRow(at: indexPath, animated: true)

This should work:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Just make sure materialTable and tableView are pointing to the same object.

Is materials connected to the tableView in Interface Builder?


use this code

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
 {
    //Change the selected background view of the cell.
     [tableView deselectRowAtIndexPath:indexPath animated:YES];
 }

Swift 3.0:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //Change the selected background view of the cell.
    tableView.deselectRow(at: indexPath, animated: true)
}

Swift

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    // your code

    // your code

    // and use deselect row to end line of this function

    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

}

Swift 3

I've run into this as well - when you navigate or unwind back to the table view it usually doesn't deselect the previously selected row for you. I put this code in the table view controller & it works well:

override func viewDidAppear(_ animated: Bool) {
    if let lastSelectedRow = tableView.indexPathForSelectedRow {
        tableView.deselectRow(at: lastSelectedRow, animated: true)
    }
}

Use the following method in the table view delegate's didSelectRowAtIndexpath (Or from anywhere)

[myTable deselectRowAtIndexPath:[myTable indexPathForSelectedRow] animated:YES];

In addition to setting the cell as selected, you also need to inform the tableView that the cell is selected. Add a call to -tableView:selectRowAtIndexPath:animated:scrollPosition: to your willDisplayCell: method: and you will be able to deselect it as normal.

- (void)tableView:(UITableView*)tableView 
  willDisplayCell:(UITableViewCell*)cell
forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        // SELECT CELL
        [cell setSelected:YES]; 
        // TELL TABLEVIEW THAT ROW IS SELECTED
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];   
    } 
}

Be sure to use UITableViewScrollPositionNone to avoid odd scrolling behavior.


Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)

Try this:

for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

It might be useful to make an extension in Swift for this.

Swift 4 and Swift 5:

Swift extension (e.g. in a UITableViewExtension.swift file):

import UIKit

extension UITableView {

    func deselectSelectedRow(animated: Bool)
    {
        if let indexPathForSelectedRow = self.indexPathForSelectedRow {
            self.deselectRow(at: indexPathForSelectedRow, animated: animated)
        }
    }

}

Use e.g.:

override func viewWillAppear(_ animated: Bool)
{
    super.viewWillAppear(animated)

    self.tableView.deselectSelectedRow(animated: true)
}

This is a solution for Swift 4

 in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

just add

tableView.deselectRow(at: indexPath, animated: true)

it works like a charm

example:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
//some code
}

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to iphone

Detect if the device is iPhone X Xcode 8 shows error that provisioning profile doesn't include signing certificate Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone Certificate has either expired or has been revoked Missing Compliance in Status when I add built for internal testing in Test Flight.How to solve? cordova run with ios error .. Error code 65 for command: xcodebuild with args: "Could not find Developer Disk Image" Reason: no suitable image found iPad Multitasking support requires these orientations How to insert new cell into UITableView in Swift

Examples related to uitableview

Adding a UISegmentedControl to UITableView make UITableViewCell selectable only while editing How to fix Error: this class is not key value coding-compliant for the key tableView.' UITableView example for Swift Swift - how to make custom header for UITableView? How to insert new cell into UITableView in Swift How to detect tableView cell touched or clicked in swift Dynamic Height Issue for UITableView Cells (Swift) UIButton action in table view cell How to get the indexpath.row when an element is activated?

Examples related to interface-builder

Could not insert new outlet connection: Could not find any information for the class named Xcode 6 Bug: Unknown class in Interface Builder file Xcode 6 Storyboard the wrong size? UIScrollView Scrollable Content Size Ambiguity How to change navigation bar color in iOS 7 or 6? How to use auto-layout to move other views when a view is hidden? Is it possible to set UIView border properties from interface builder? Should IBOutlets be strong or weak under ARC? How to make UIButton's text alignment center? Using IB Change button text from Xcode?

Examples related to ui-select2

How to get Selected Text from select2 when using <input> How do I change selected value of select2 dropdown with JqGrid? Update select2 data without rebuilding the control set the width of select2 input (through Angular-ui directive) Is there a SELECT ... INTO OUTFILE equivalent in SQL Server Management Studio? Can I apply the required attribute to <select> fields in HTML5? jQuery UI tabs. How to select a tab based on its id not based on index How To Get Selected Value From UIPickerView UIButton: set image for selected-highlighted state How can I pass selected row to commandLink inside dataTable or ui:repeat?