35

How do you disable selecting only a single cell in a UITableView? I have several, and I only want the last to be disabled.

JosephH
  • 37,173
  • 19
  • 130
  • 154
Dexter
  • 5,666
  • 6
  • 33
  • 45
  • possible duplicate of [UITableview: How to Disable Selection for Some Rows but Not Others](http://stackoverflow.com/questions/2267993/uitableview-how-to-disable-selection-for-some-rows-but-not-others) – JosephH Jan 30 '14 at 13:36

9 Answers9

53

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. It will also make voiceover treat it the same as a dimmed button (which may or may not be what you want).

Note that if you have interactive elements in the cell (ie. switches/buttons), you'll need to use cell.selectionStyle = UITableViewCellSelectionStyleNone; instead and then make sure to ignore taps on the cell in tableView:didSelectRowAtIndexPath:.

JosephH
  • 37,173
  • 19
  • 130
  • 154
  • Try doing this on the view that receives the highlight. Otherwise, it is the same as disabling the cell. – Nate Symer Sep 16 '12 at 02:46
  • 4
    I can't use this because it also disables `cell.accessoryView`, which I've set to a `UIButton` that I want to be tappable. – ma11hew28 Dec 21 '12 at 03:46
  • Additionally, this will cause Voice Over to incorrectly treat the cell as a dimmed button instead of static text (with an optional accessory). – Endersstocker Jan 30 '14 at 12:06
  • @Endersstocker Thanks, that's useful extra info - I've mentioned that in my answer so it's more prominent. (I guess in some situations that may be want people want, depending why they're disabling the cell?) – JosephH Jan 30 '14 at 13:41
51
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UITableViewCell *cell = ...

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

}
Tom Irving
  • 10,041
  • 6
  • 47
  • 63
Camilo Sanchez
  • 1,528
  • 1
  • 14
  • 18
  • 34
    This will prevent the cell from appearing to be selected, but `tableView:didSelectRowAtIndexPath:` will still be called. – Brian Aug 30 '10 at 19:39
  • Using both `cell.selectionStyle = .None` and `cell.userInteractionEnabled = false` combined will cover most scenarios. – SwiftArchitect Feb 04 '16 at 20:04
19

Throw this in your custom Table VC:

// cells lacking UITableViewCellAccessoryDisclosureIndicator will not be selectable
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    if (cell.accessoryType != UITableViewCellAccessoryDisclosureIndicator) {
        return nil;
    }
    return indexPath;
}

// disabled cells will still have userinteraction enabled for their subviews
- (void)setEnabled:(BOOL)enabled forTableViewCell:(UITableViewCell *)tableViewCell
{
    tableViewCell.accessoryType = (enabled) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
    // if you dont want the blue selection on tap, comment out the following line
    tableViewCell.selectionStyle = (enabled) ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone;
}

Then to enable/disable selection for someTableViewCell, do this:

[self setEnabled:state forTableViewCell:someTableViewCell];

You're done and can ship.

11
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self numberOfRowsInSection] == [indexPath row]) {
        return nil;
    } else {
        return indexPath;
    }
}

the last row of the table will not be selected

Aaron Saunders
  • 33,180
  • 5
  • 60
  • 80
  • 1
    This will prevent the cell from actually being selected, but it will still be highlighted when the user touches it – Brian Aug 30 '10 at 21:07
  • 2
    Sorry, need to add UITableViewCellSelectionStyleNone style to the cell – Aaron Saunders Aug 30 '10 at 21:15
  • 1
    I might add that setting the tableview selection style should be done in cellForRowAtIndexPath: to avoid lag when loading the TableView (the table view takes a good 1-2 to disable selection for the cell). – Nate Symer Sep 16 '12 at 02:52
2

As I mentioned in another thread all the above methods are not solving the problem precisely. The correct way of disabling a cell is through the method

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

and in that method one has to use

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

which disables cell selection but still allows the user to interact with subviews of the cell such as a UISwitch.

Community
  • 1
  • 1
MightyMouse
  • 13,208
  • 8
  • 33
  • 43
1

The cleanest solution that I have found to this only makes use of the delegate method willDisplayCell.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == 0) //<-----ignores touches on first cell in the UITableView
    {                        //simply change this around to suit your needs
        cell.userInteractionEnabled = NO;
        cell.textLabel.enabled = NO;
        cell.detailTextLabel.enabled = NO;
    }
}

You don't have to take any further action in the delegate method didSelectRowAtIndexPath to ensure that the selection of this cell is ignored. All touches on this cell will be ignored and the text in the cell will be grayed out as well.

Scooter
  • 4,068
  • 4
  • 32
  • 47
0

with iOS 6.

You can use the following delegate method and return NO in case you don't it to be selected and YES in case you want it to be selected.

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath.section == 0;
}
mohamede1945
  • 7,092
  • 6
  • 47
  • 61
0

Try this in swift:

self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
Masa S-AiYa
  • 670
  • 6
  • 13
0

If anyone wondering how to achieve this in swift then here is my code. I am using Xcode 7 and tested using iPad Retina(iOS 9).

cell.selectionStyle = UITableViewCellSelectionStyle .None
cell.userInteractionEnabled = false

Try to place this two line code whether you want. In my case I have used this in this method for displaying cells.

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)

Remember this two line code will block any kind of selection or interaction to your cells but you can only use the first line individually if you want. That is...

cell.selectionStyle = UITableViewCellSelectionStyle .None

Only this line will block the selection to your cells.

However the second line will make the cell "Read-Only". That is..

cell.userInteractionEnabled = false

Thanks

Hope this helped.

onCompletion
  • 6,500
  • 4
  • 28
  • 37