views:

1096

answers:

1

I have a UITableView with a single section and 'n' rows (populated from an NSMutableArray, myTableArray). When entering Edit mode, I would like to achieve the following:

  • setup the "n" rows to have the UITableViewCellEditingStyleDelete editing style
  • insert a new row, above the original 'n', and set it up to have the UITableViewCellEditingStyleInsert editing style

My UITableViewController subclass is implemented as follows:

- (void)setEditing:(BOOL)flag animated:(BOOL)animated
{
    [super setEditing:flag animated:animated];

    UITableView *tableView = (UITableView *)self.view;
    NSArray *topIndexPath = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];

    if (self.editing == YES)
        [tableView insertRowsAtIndexPaths:topIndexPath withRowAnimation:UITableViewRowAnimationBottom];
    else
        [tableView deleteRowsAtIndexPaths:topIndexPath withRowAnimation:UITableViewRowAnimationBottom];
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0)
        return UITableViewCellEditingStyleInsert;
    else
        return UITableViewCellEditingStyleDelete;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (self.editing == YES)
        return [myTableArray count] + 1;
    else
        return [myTableArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // ... boiler-plate dequeueReusableCellWithIdentifier code, etc ...

    if (self.editing == YES)
    {
        if (indexPath.row == 0)
            cell.textLabel.text = @"My new row";
        else
            cell.textLabel.text = [myTableArray objectAtIndex:(indexPath.row - 1)];
    }
    else
    {
        cell.textLabel.text = [myTableArray objectAtIndex:indexPath.row];
    }

    return cell;
}

When this code is run, and the Edit button is pressed, a new row is inserted above the original 'n' rows, however, the second row, in addition to the first, has the UITableViewCellEditingStyleInsert editing style. For example, if 'n' is 3, after the Edit button is pressed the table displays:

  • row 0: insert editing style
  • row 1: insert editing style (should be delete)
  • row 2: delete editing style
  • row 3: delete editing style

After further investigation, I've noticed that if 'n' is 3 and the Edit button is pressed, the method tableView:editingStyleForRowAtIndexPath: is called a total of 8 times:

  • [super setEditing:flag animated:animated] results in 3 calls for each of the original rows 0, 1 and 2
  • the subsequent [tableView insertRowsAtIndexPaths:topIndexPath withRowAnimation:UITableViewRowAnimationBottom] results in 5 calls for rows 0, 1, 2, 3, and then 0 again

I can understand that the editing style needs to be re-corrected as a result of inserting a new row, however I do not understand why in the last 5 calls, row 0 is set twice and why row 1 still manages to have the incorrect style.

Does anyone have any insight?

A: 

Try turning off the animation for the insert and see how many times things get called.

The problem you've got here is that super is being called when row zero is the existing pre-inserted row, then you're doing the insert with animation, which is causing the editingStyle.. method to be called.

The following suggestion is scary, but you could also try doing the test for editing before calling super, and do the row insert/delete and THEN call super. that way the proper number of rows are in place.

The bigger question is...are you sure you want the insert row to be the top one? That's a non-standard place to put it and unless you have a darned good reason to go against UI guidelines, you might want to consider reworking your UI to put the insert styled row at the bottom....

God of Biscuits
Which UI guidelines are you referring to when you say it is non-standard to insert a row at the top? The iPhone Human Interface Guidelines?
Ben Lever
Yes. And I'll add that it's a de facto standard to put the Insert-styled-for-editing row (with the green plus sign) as the last row in each section for which you're allowing adds.That is, of course, unless you have very good reasons to do the insertions elsewhere.
God of Biscuits