Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does setEditing:animated: and insertRowsAtIndexPaths: result in this weird editing style animation?

I've got a UITableView on which I'm toggling setEditing:animated: on, to allow the user to insert and delete rows. When editing is turned on, I want a new insert new item row to be added to the table and then I want the editing controls to animate in like normal. I don't want the new insert new item row to animate in on its own, using something like a fade. I want it to just appear, and then slide in like any existing table data source rows do.

Here's what is happening as a result of my current code, though (click for larger view):

The top row does what I want - it simply slides over and the delete icon fades in. When it disappears, the delete icon fades out and the row expands again.

The second row is my non-data-source row that I add to the table myself. On appearing, it does not animate in at all. The insert icon and row appear all at once and do not slide in. When it disappear, the row expands nicely, but the plus icon slides with it. The animation is occurring for the entire row, and not for the plus icon and then row separately, like the first row.

Here's a quick run-down of my code, but I think providing a link to the class file might be better.

When an edit button on my toolbar is pressed, I call my UIViewController method setEditing:animated:. In this method, I do the following ...

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {

    [super setEditing:editing animated:animated];

    // keep the table in the same editing mode
    [_table setEditing:editing animated:animated];

    if (editing) {

        [_table insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_channels.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

    } else {

        [_table deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_channels.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

    }

}

This is where the animations of the inserting is occuring. I've tried wrapping the whole thing in [_table beginUpdate] and endUpdate, as well as just the row insertion. Neither seems to produce the clean animation I'm aiming for.

Any ideas what I might be missing? The whole code file is here:

https://github.com/ryancole/pound-client/blob/master/pound-client/controllers/ChannelListViewController.m#L106-L127

like image 748
Ryan Avatar asked Jan 09 '13 02:01

Ryan


2 Answers

The super call does the sliding 'to editing' animation so if you insert something after it, it won't take part in it. What you want to do is insert the row before that call and remove the row after. You'll also need to keep track of the rows with a different boolean.

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {

    _amEditing = editing;

    if (editing) {

        [_table insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_channels.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

    } 

    [super setEditing:editing animated:animated];

    // keep the table in the same editing mode
    [self.view setEditing:editing animated:animated];

    if (!editing)
    {
        [_table deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_channels.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
    }


}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _amEditing ? _channels.count + 1 : _channels.count;
}

UPDATE:

The second to last row's icon still has a strange animation.. to work around this you can add a delay to the deletion..

    if (!editing)
    {
        [self performSelector:@selector(deleteLastRow) withObject:nil afterDelay:0.25];
    }

-(void) deleteLastRow
{
    [self.view deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_objects.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
like image 141
Krys Jurgowski Avatar answered Nov 02 '22 23:11

Krys Jurgowski


As is commented you have to call [super setEditing:editing animated:animated] after you insert the row

 - (void)setEditing:(BOOL)editing animated:(BOOL)animated {

    // remove this [super setEditing:editing animated:animated];

    // keep the table in the same editing mode
    [_table setEditing:editing animated:animated];

    if (editing) {

        [_table insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_channels.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

    } else {

        [_table deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_channels.count inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

    }
  [super setEditing:editing animated:animated]; // add it here

}
like image 39
Guilherme Torres Castro Avatar answered Nov 03 '22 00:11

Guilherme Torres Castro