Reputation: 4248
I have a table view with two rows in one section, i.e
---
Row A
Row B
If I want to animate row 1 into a new section, i.e. the end result being:
---
Row B
---
Row A
how should this be achieved? What I have tried already is:
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow: 0 inSection: 0]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView insertSections:[NSIndexSet indexSetWithIndex: 1] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
However, in iOS 8 at least, the row animates out but then the new section is un-rendered (i.e. white, no bottom row border) until some time after when something triggers a redraw and it comes back.
[self.tableView beginUpdates];
[self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
[self.tableView endUpdates];
Which raises an exception:
Invalid update: invalid number of sections. The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).
And:
[self.tableView beginUpdates];
[self.tableView insertSections:[NSIndexSet indexSetWithIndex: 1] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
[self.tableView endUpdates];
Which raises the exception:
cannot move a row into a newly inserted section (1)
Should I just not animate at all and reload the whole table?
Upvotes: 5
Views: 2050
Reputation: 1073
You'll need to perform this in two steps.
First you'll need to add the section; you need to tell your data source to account for the new section. For a simple example like yours, you can just set a variable:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if(hasTwoSections)
return 2;
return 1;
}
Then where you want to trigger the animation, call:
hasTwoSections = true; // this needs to be set before endUpdates
[self.tableView beginUpdates];
[self.tableView insertSections:[NSIndexSet indexSetWithIndex: 1] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
At this point, the tableView will call the data source methods to update the table based on your changes.
Once the section has been added, you can move the row to it in another update block:
[self.tableView beginUpdates];
[self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
[self.tableView endUpdates];
Obviously you'll need to update what numberOfRowsInSection returns to account for the change.
Although it's two steps, it will look like it's happening all at once.
Upvotes: 4
Reputation: 7379
I was in a similar situation where I was getting the exception cannot move a row into a newly inserted section (1)
. I only found two half solutions.
reloadData()
- aggressive, and no animationsself.requestTableView.deleteRowsAtIndexPaths([oldIndexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
self.requestTableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
To get animations effects that give the impression of the rows moving, you could use UITableViewRowAnimation.Top
when deleting, inserting, or reloading sections.
self.tableView.deleteSections(toDelete, withRowAnimation: UITableViewRowAnimation.Top)
self.tableView.insertSections(toInsert, withRowAnimation: UITableViewRowAnimation.Top)
self.tableView.reloadSections(toReload, withRowAnimation: UITableViewRowAnimation.Top)
Upvotes: 0