引子:昨天一个前同事问我面试的时候面试官问不使用reloadData怎么更新cell的删除和添加,他说回答了用reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation这些API面试官说不正确。然后他问面试官使用什么方法,面试官绷着脸说让他自己看第三方库,哈哈哈,其实这个问题比较基础,做过列表动画的开发应该都会的。
UITableView删除添加、对指定cell动画、更改UITableView的cell的样式等,应该通过调用beginUpdates 和 reloadRowsAtIndexPaths 来实现效果,而不是调用tableview的reloadData方法去重新加载全部的cell。Updates方法不会重复的代用cellForRowAtIndexPath:方法。
- (void)beginUpdates;
- (void)endUpdates;
当然在iOS11之后Apple提倡我们使用:
// Allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion API_AVAILABLE(ios(11.0), tvos(11.0));
- 如删除cell的动画操作:
// 1. 更新数据
[self.dataSource removeObjectAtIndex:0];
// 2. 更新UI
[self.tableView beginUpdates];
NSIndexPath *index = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:index] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
- 添加cell的动画:
// 1. 模拟数据添加
NSMutableArray *muArr = [[NSMutableArray alloc] initWithArray: self.dataSource];
[muArr addObject:[self.dataSource firstObject]];
self.dataSource = muArr.copy;
// 2. 更新UI
[self.tableView beginUpdates];
NSIndexPath *index = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:index] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
- 更改对应cell的样式等
[self.tableView beginUpdates];
NSIndexPath *index = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:index] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];