7

I've got a UITableView which is automatically set up for multiple selection in Edit Mode using the following lines in viewDidLoad:

self.tableView.allowsMultipleSelectionDuringEditing = YES;
[self setEditing:YES animated:YES];

However, I'd like to indicate that a row was selected by changing its background color, rather than by the checkmarks which automatically appear along the left of each row. (For example, the ones that appear when editing the email list in the Mail app, or being discussed in this SO question.) I've got it working for the most part, except that I can't get those checkboxes, which are automatically created as part of putting the UITableView into Edit Mode, to go away.

Below is the code I'm working with:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _Hierachy.cellCount;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *testCell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if(testCell == nil) {
        testCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    [[testCell textLabel] setText:@"Test Cell"];

    return testCell;
}

Those are the only UITableView methods I've got so far, so everything else should be default behavior.

Does anyone know how to hide those checkmarks along the left, in Edit Mode? I've seen many questions about checkmarks in the accessory portion of the cell, but as I understand it, this is a different thing. I've also seen people talk about the tableView:didSelectRowAtIndexPath: method, but these checkmarks are created when the table enters Edit mode and dismissed when the user taps "Done," so that method doesn't seem related.

The closest I've come is finding this method:

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
    return NO;
}

But that just prevents the cell's content from indenting to make room for the checkmarks. The checkmarks still appear.

Surely there's a way to hide those checkmarks, and still allow multiple selection in Edit Mode? Or are those checkmarks seriously mandatory behavior for a UITableView in Edit Mode with Multiple Selection enabled?

EDIT: I am (reluctantly) open to answers that are somewhat hack-y, like moving the frame of the checkmarks until it's off the screen. This app is for internal use, and won't need to be approved for the App Store. But given that the checkmarks are created automatically when the UITableView moves into Edit Mode, I don't even know how to get them as objects to alter. Any help would be appreciated!

Community
  • 1
  • 1
Nerrolken
  • 1,975
  • 3
  • 24
  • 53

3 Answers3

10

You'll have to subclass your UITableViewCell and override the (void)setEditing:animated: method like this:

#import "MyCustomCell.h"

@implementation MyCustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (void)setSelectedBackgroundView:(UIView *)selectedBackgroundView
{
    //Cell Selected Color: CLEAR
    [super setSelectedBackgroundView:selectedBackgroundView];
}

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    //Cell Edit Mode NO Indent & Selected Color: CLEAR
    [super setEditing:NO animated:animated];
    [self setNeedsLayout];
}

@end

After you do that, go to Inteface Builder and make your cell part of the class MyCustomCell.

After you make your cell part of MyCustomCell class in IB, import MyCustomCell.h in your UITableViewController and modify the following in your code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCustomCell *testCell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if(testCell == nil) {
        testCell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    [[testCell textLabel] setText:@"Test Cell"];

    return testCell;
}

UPDATE: You could also do the following in your TableView's tableView:editingStyleForRowAtIndexPath:

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

{
            return UITableViewCellEditingStyleNone;
}

But you will get your cell indented. To remove that indent you'll have to subclass the Cell.

You should be good to go after doing this! I've just tested it and it works the way you want it!

Razvan
  • 4,122
  • 2
  • 26
  • 44
  • Excellent, thank you! I did get an odd deletion of the separators between cells during selection (as per [this SO question](http://stackoverflow.com/q/19212476/1418688)), but between this answer and one of those, I got it working perfectly! Thanks! :) I'll confirm the bounty as soon as I can (in 22 hours). – Nerrolken Oct 03 '14 at 19:16
  • Oh, I had an issue with the separators not disappearing (custom background image) :). I had to fast enumerate the subviews of the cell to get it right. I'm glad you've figured it out! – Razvan Oct 03 '14 at 19:22
  • Nice one! Thank you. – Thomás Pereira May 17 '19 at 19:10
1

Here is the most simple solution for multiple selection with no checkmarks:

- (BOOL)tableView:(UITableView*)tableView canEditRowAtIndexPath:(NSIndexPath*)indexPath {
    return NO;
}

This will cause the cells to be selected using the default selection style (gray or using your custom selection background), and no checkmarks will appear.


A word on whatever solution you pick. Users expect a consistent experience across multiple applications, and these checkmarks are part of this consistency. Make sure to have a good reason to change a normal OS look and feel.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • 1
    That's not a valid answer! Doing so will not allow the cell to be deleted anymore! – Razvan Oct 03 '14 at 18:45
  • 1
    @codeFi I do not see anywhere in the question a requirement to delete cells. Only multiple selection. – Léo Natan Oct 03 '14 at 18:46
  • 2
    Documentation: The method permits the data source to exclude individual rows from being treated as editable. Editable rows display the insertion or deletion control in their cells. If this method is not implemented, all rows are assumed to be editable. Rows that are not editable ignore the editingStyle property of a UITableViewCell object and do no indentation for the deletion or insertion control. Rows that are editable, but that do not want to have an insertion or remove control shown, can return UITableViewCellEditingStyleNone from the tableView:editingStyleForRowAtIndexPath: delegate... – Razvan Oct 03 '14 at 18:52
  • And I get your point. But usually an editable cell means that it should also have delete enabled. – Razvan Oct 03 '14 at 18:54
0

here is how to achieve:

  1. swipe to delete works
  2. you don't see the checkbox, delete item or anything else on the left of the cell when in editing mode
  3. Cell indentation still works normally (you can turn this off if you want)
  4. (bonus) Support multiple selection

so - in your UITableViewDelegate

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.isEditing)
    {
      return UITableViewCellEditingStyleNone;
    }
    else
    {
      return UITableViewCellEditingStyleDelete;
    } 
}

- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{
  (do stuff)
}

you also need to configure your UITableView

self.table.allowsMultipleSelectionDuringEditing=NO;

now if you actually do want multiple selection;

self.table.allowsSelectionDuringEditing=YES;

then manage the selected cells yourself.

I put a custom checkbox in my UITableViewCell subclass, and I also change the value in response to

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

The questioner wants to indicate selection with the background colour - that part should be straightforward.

Confused Vorlon
  • 9,659
  • 3
  • 46
  • 49