UITableview: How to Disable Selection for Some Rows but Not Others

0 votes
asked Feb 15, 2010 by warrior

I am displaying in a group tableview contents parsed from XML. I want to disable the click event on it (I should not be able to click it at all) The table contains two groups. I want to disable selection for the first group only but not the second group. Clicking the first row of second group navigates to my tube player view.

How can I make just specific groups or rows selectable?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if(indexPath.section!=0)
    if(indexPath.row==0)    

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:tubeUrl]];   
}

Thanks.

19 Answers

0 votes
answered Jan 15, 2010 by techzen

You trap selections with these data source methods.

– tableView:willSelectRowAtIndexPath: 
– tableView:didSelectRowAtIndexPath: 
– tableView:willDeselectRowAtIndexPath: 
– tableView:didDeselectRowAtIndexPath:

In these methods, you check if the selected row is one you want to be selectable. If it is, take an action, if not, do nothing.

Unfortunately, you can't turn off selection for just one section. It's the whole table or nothing.

You can however set the table cells selectionStyle property to UITableViewCellSelectionStyleNone. I believe that will make the selection invisible. Combined with the above methods that should make the cells look completely inert from the user's perspective.

Edit01:

If you have a table in which only some of the rows are selectable it is important that the cells of the selectable rows be visually distinct from the non-selectable rows. The chevron accessory button is the default way to do this.

However you do it, you don't want your users trying to select rows and thinking the app has malfed because the row doesn't do anything.

0 votes
answered Jan 15, 2010 by brian-chapados

If you want to make a row (or subset of rows) non-selectable, implement the UITableViewDelegate method -tableView:willSelectRowAtIndexPath: (also mentioned by TechZen). If the indexPath should be not be selectable, return nil, otherwise return the indexPath. To get the default selection behavior, you just return the indexPath passed to your delegate method, but you can also alter the row selection by returning a different indexPath.

example:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // rows in section 0 should not be selectable
    if ( indexPath.section == 0 ) return nil;

    // first 3 rows in any section should not be selectable
    if ( indexPath.row <= 2 ) return nil;

    // By default, allow row to be selected
    return indexPath;
}
0 votes
answered Feb 15, 2010 by pugal

You just have to put this code into cellForRowAtIndexPath

To disable the cell's selection property:(While tapping the cell).

cell.selectionStyle = UITableViewCellSelectionStyle.none

To enable being able to select (tap) thecell:(tapping the cell).

// Default style
cell.selectionStyle = UITableViewCellSelectionStyle.blue

// Gray style
cell.selectionStyle = UITableViewCellSelectionStyle.gray

Note that a cell with selectionStyle = UITableViewCellSelectionStyleNone will still cause the UI to call didSelectRowAtIndexPath when touched by the user. To avoid this, do as suggested below and set.

cell.userInteractionEnabled = false

instead. Also note you may want to set cell.textLabel.enabled = false to grey out the item.

0 votes
answered Jan 1, 2011 by josephh

To stop just some cells being selected use:

cell.userInteractionEnabled = NO;

As well as preventing selection, this also stops tableView:didSelectRowAtIndexPath: being called for the cells that have it set.

0 votes
answered Jan 14, 2011 by pt2ph8

Use this to make the cell look like it is disabled and non-selectable:

cell.selectionStyle = UITableViewCellSelectionStyleNone;

Important: note that this is only a styling property, and does not actually disable the cell. In order to do that, you have to check for selectionStylein your didSelectRowAtIndexPath: delegate implementation:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if(cell.selectionStyle == UITableViewCellSelectionStyleNone) {
        return;
    }

    // do your cell selection handling here
}
0 votes
answered Jan 12, 2012 by azfar

You need to do something like the following to disable cell selection within the cellForRowAtIndexPath method:

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell setUserInteractionEnabled:NO];

To show the cell grayed out, put the following within the tableView:WillDisplayCell:forRowAtIndexPath method:

[cell setAlpha:0.5];

One method allows you to control the interactivity, the other allows you to control the UI appearance.

0 votes
answered Jan 22, 2012 by mightymouse

None from the answers above really addresses the issue correctly. The reason is that we want to disable selection of the cell but not necessarily of subviews inside the cell.

In my case I was presenting a UISwitch in the middle of the row and I wanted to disable selection for the rest of the row (which is empty) but not for the switch! The proper way of doing that is hence in the method

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

where a statement of the form

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

disables selection for the specific cell while at the same time allows the user to manipulate the switch and hence use the appropriate selector. This is not true if somebody disables user interaction through the

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

method which merely prepares the cell and does not allow interaction with the UISwitch.

Moreover, using the method

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

in order to deselect the cell with a statement of the form

[tableView deselectRowAtIndexPath:indexPath animated:NO];

still shows the row being selected while the user presses on the original contentView of the cell.

Just my two cents. I am pretty sure many will find this useful.

0 votes
answered Jan 29, 2013 by abdul-rahman

You can use the tableView:willDisplayCell method to do all the kinds of customization to a tableViewCell.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
     [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
     [cell setUserInteractionEnabled:NO];

     if (indexPath.section == 1 && indexPath.row == 0)
     {
         [cell setSelectionStyle:UITableViewCellSelectionStyleGray];
         [cell setUserInteractionEnabled:YES];
     }
} 

In this above code, the user can only select the first row in the second section of the tableView. The rest all rows can't be selected. Thanks!~

0 votes
answered Jan 2, 2014 by rick-royd-aban

SIMPLE

Just use cell.userInteractionEnabled = YES; to the cell if it can navigate and cell.userInteractionEnabled = NO; otherwise

0 votes
answered Jan 2, 2014 by esqarrouth

For swift:

cell.selectionStyle = .None
cell.userInteractionEnabled = false
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...