strave
strave

Reputation: 1481

tableView's insertRowsAtIndexPath doesn't call tableView's cellForRowAtIndexPath

I have a UITableViewController with an Edit button. When this is clicked, the user can delete or add rows to the UITableView. Deleting rows works fine. But when I want to add a new row, I get a short animation of an empty cell coming from the left and when the animation is over, the table view looks exactly as it looked before the method was called. When I add a new cell, I add a new object to the data array that feeds my table view and then add the cell. That data array gets updated. So if I call [tableView reloadData] after I have added the new cell, I get to see the new cell but without any animation. And I really would like to have the animation as well.

I have a working example of the same thing. I realized that after tableView:commitEditingStyle:forRowAtIndexPath: gets called, the table view's data source method tableView:cellForRowAtIndexPath: gets automatically called. In my case, it doesn't. I guess that's the reason why I'm not seeing the new cell. Any ideas why this is happening?

This is my `tableView:commitEditingStyle:forRowAtIndexPath:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    {
        // Delete the row from the data source
        [self.tableData removeObjectAtIndex:[indexPath row]];

        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:self.tableData forKey:self.key];
        [defaults synchronize];

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) 
    {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
        UITextField *textField = (UITextField *)[[cell contentView] viewWithTag:kTextFieldTag];
        NSString *textFieldText = [textField text];
        if (textFieldText != nil) 
        {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
            NSString *string = [[NSString alloc] initWithString:textFieldText];
            [self.tableData addObject:string];
            [string release];

            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            [defaults setObject:self.tableData forKey:self.key];
            [defaults synchronize];

            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];   

            // If reloadData is being called, the new cell is displayed but without the animation
            // [tableView reloadData]; 
        } 
        else
        {
            // Display alert view
            // Code for displaying an AlertView
        }
    }   
}

Upvotes: 1

Views: 4054

Answers (2)

Samantha John
Samantha John

Reputation: 978

I'm having this same issue. From what I can tell, the UITableView only calls cellForRowAtIndexPath if it thinks the cell being changed is visible. Since you are adding a new cell I'm guessing the table does not think it's visible and therefore does not call the method. Jaminguys solution works for me, but it sounds a bit like a bug in UIKit.

This method does work if you are inserting cells in the middle of the table view, incidentally.

Upvotes: 1

jaminguy
jaminguy

Reputation: 25930

Try wrapping your insert call with [tableView beginUpdates] [tableView endUpdates]. From the docs:

If you do not make the insertion, deletion, and selection calls inside this block, table attributes such as row count might become invalid.

[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[tableView endUpdates];

Upvotes: 2

Related Questions