Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird UITableView insert/delete row animation

Tags:

I'm seeing a weird effect when inserting/deleting a UITableViewCell in a UITableView with animation (UITableViewRowAnimationTop).

The animation glitch happens when the cell to insert is much bigger than the cell above.

This video shows the glitch in the simulator, yellow cell appears suddenly out of no where when it's supposed to slide from top.

Here is the Xcode project from the video.

Bellow is the cell insertion/animation code.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return 2 + self.thirdCellVisible; }  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {     [tableView deselectRowAtIndexPath:indexPath animated:NO];      if (indexPath.row == 1)     {         if (self.thirdCellVisible)         {             self.thirdCellVisible = !self.thirdCellVisible;             [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]                              withRowAnimation:UITableViewRowAnimationTop];         }         else         {             self.thirdCellVisible = !self.thirdCellVisible;             [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]                              withRowAnimation:UITableViewRowAnimationTop];         }     } }  - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {     if (indexPath.row == self.thirdCellIndexPath.row)     {         return 100.0f;     }      return 44.0f; } 
like image 917
Nicolas Jakubowski Avatar asked Apr 11 '14 19:04

Nicolas Jakubowski


2 Answers

You will have to call

[tableView beginUpdates]  

and

[tableView endUpdates]  

before and after calling insert/delete methods as below :

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return 2 + self.thirdCellVisible; }  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {     [tableView deselectRowAtIndexPath:indexPath animated:NO];      if (indexPath.row == 1)     {         if (self.thirdCellVisible)         {             self.thirdCellVisible = !self.thirdCellVisible;             [self.tableView beginUpdates];              [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]                              withRowAnimation:UITableViewRowAnimationTop];              [self.tableView endUpdates];          }         else         {             self.thirdCellVisible = !self.thirdCellVisible;             [self.tableView beginUpdates];              [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]                              withRowAnimation:UITableViewRowAnimationTop];              [self.tableView endUpdates];          }     } }  - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {     if (indexPath.row == self.thirdCellIndexPath.row)     {         return 100.0f;     }      return 44.0f; } 
like image 97
Pooja Patel Avatar answered Oct 30 '22 09:10

Pooja Patel


According to Apple here:

To animate a batch insertion, deletion, and reloading of rows and sections, call the corresponding methods within an animation block defined by successive calls to beginUpdates and endUpdates. If you don’t call the insertion, deletion, and reloading methods within this block, row and section indexes may be invalid. Calls to beginUpdates and endUpdates can be nested; all indexes are treated as if there were only the outer update block.

At the conclusion of a block—that is, after endUpdates returns—the table view queries its data source and delegate as usual for row and section data. Thus the collection objects backing the table view should be updated to reflect the new or removed rows or sections.

You will have to call [tableView beginUpdates] and [tableView endUpdates] before and after calling insert/delete methods respectively.

An example is provided by Apple on the above link.

Note: If your array and table view items are out of sync, without the begin/end calls an exception will be thrown.

Suggestion: Try first withRowAnimation:UITableViewRowAnimationAutomatic

like image 38
Nishant Avatar answered Oct 30 '22 08:10

Nishant