-
背景
需求要实现一个列表中cell被删除的动画效果,UI要求cell之间有 10pt的间隔,所以通过在自定义cell的setFrame方法中修改fram的height 达到了分段的tableView效果。
-
问题
在调用了deleteRowsAtIndexPaths和reloadRowsAtIndexPaths后, 发现cell的高度被多次修改导致 fram比预计的小了10pt(分段间隔的高度)
-
原因
先说原因 重载部分cell、删除cell、插入cell的动作是在原来cell的位置用新的cell替换,原cell的height已经调用setFrame,新的cell也会走一遍setFrame,所以最后会发现 可视的所有cell都会出现间隔放大10pt(fram.size.height 小了10pt)
-
解决方案
放弃在setframe中修改fram的实现cell分段的间隔效果的方式,而是在contentview中布局实现(添加view类似,不再赘述)。
缺点:如果cell 有整体的点击效果或者左滑动业务会导致间隔也在操作范围内,尤其是由于点击背景色时。
重新了解下这几个方法:
- (void)beginUpdates;
- (void)endUpdates;
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
The UITableView class allows you to insert, delete, and reload a group of rows or sections at one time, animating the operations simultaneously in specified ways. The eight methods shown in Listing 7-7 pertain to batch insertion and deletion. Note that you can call these insertion and deletion methods outside of an animation
文档告诉我们
UITableView允许您一次插入、删除和重新加载 部分rows或者sections ,同时指定动画的操作方式。上面所示的八个方法适合批量插入和删除。注意,您可以调用这些插入和删除方法之外的一个动画
demo about Inserting and deleting a block of rows in a table view
> - (IBAction)insertAndDeleteRows:(id)sender {
// original rows: Arizona, California, Delaware, New Jersey, Washington
[states removeObjectAtIndex:4]; // Washington
[states removeObjectAtIndex:2]; // Delaware
[states insertObject:@"Alaska" atIndex:0];
[states insertObject:@"Georgia" atIndex:3];
[states insertObject:@"Virginia" atIndex:5];
NSArray *deleteIndexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:2 inSection:0],
[NSIndexPath indexPathForRow:4 inSection:0],
nil];
NSArray *insertIndexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:3 inSection:0],
[NSIndexPath indexPathForRow:5 inSection:0],
nil];
UITableView *tv = (UITableView *)self.view;
[tv beginUpdates];
[tv insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[tv deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[tv endUpdates];
// ending rows: Alaska, Arizona, California, Georgia, New Jersey, Virginia
}
操作的执行顺序
在上面的例子中,你肯定注意到 deleteRowsAtIndexPaths:withRowAnimation:方法写在 insertRowsAtIndexPaths:withRowAnimation:之后。然而,这并不是tableView真正的操作顺序。实际上,所有的插入和重载都会在删除动作完成之后才执行。
上面的使用场景是我们经常会用到的,但是大家使用过程中要结合实际场景比如:
1.如果你的操作是通过cell 的block回调传递indexPath实现的话,就需要考虑前面执行的cell在删除和增加之后 是否需要重新配置后面cell已经拿到的indexPath,否则可能导致数组越界的问题。
2.如果deleteRowsAtIndexPaths:的row为该section的最后一行(indexPath.row = 0),就需要调用deleteSections:删除整个section。