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; }
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; }
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With