更新 UITableView 使用的数据模型数组的正确方法
The proper way to update data-model array used by UITableView
我猜我们应该倾向于为 UITableView
使用的数据模型数组使用不可变数组。关于这个的阅读在互联网上非常不同。我会说这可以防止在 tableview 显示数据时修改数组。例如,如果发生上述情况,numberOfRowsInSection:
方法可能会出现问题,对吧(即使我知道这在理论上是可能的,但我仍然无法真正想到这种情况如何在现实世界中发生)?
现在,在 commitEditingStyle:forRowAtIndexPath:
方法中,我正在这样做(messagesArray 是可变的):
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
Message *message = messageArray[indexPath.row];
[messagesArray removeObject:message];
[self.messageTable deleteRowsAtIndexPaths:[NSArray arrayWithObject: indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
而不是(messagesArray
不可变):
NSMutableArray *temp = [NSMutableArray arrayWithArray:messagesArray];
[temp removeObject:message];
messagesArray = [NSArray arrayWithArray:temp];
如果 messageArray
是不可变的,则后一个代码是我必须做的。
现在我有两个问题...IMO(如果我错了请纠正我),在上面的方法中以两种方式从数组中删除一个对象具有相同的效果。 messagesArray 最终删除了一个元素。就是这样......但是像后面的例子那样做,让我拥有不可变的数据模型数组。
有人可以评论在删除单元格后更新数据模型数组的实际首选方式(或者我可以说正确的方式吗?)?
我更愿意有一个 mutable 数组,但将其设为私有。然后,如果另一个 class 需要更改数组,您可以提供一个 add()
方法和一个 delete()
方法。两者都将负责更新数组和 table 视图。
从 table 视图的角度来看,您的数据源使用什么结构来组织数据并不重要。 table 视图不直接访问该结构。它在需要时向数据源询问它需要的部分。
现在,您是对的:您可以通过更改支持数据来搞砸您的 table 视图。但无论特定集合的可变性如何,都会发生这种情况。你的 immutable 数组片段做同样的事情:table 视图不知道有什么改变,直到你用 deleteRowsAtIndexPaths:animated
通知 它。在数据源更新时重新加载 table 视图是 必不可少的,无论您的数据源在内部做什么。
Swift 3 版本:
func tableView(_ tableView: UITableView, commit editingStyle:
UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
//1. remove data from model
dataSource.remove(at: indexPath.row)
//2. remove row from view
tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)
}
}
是的!实现滑动删除时不需要重新加载数据! UITableView
处理它。你只需要更新你的数据源
我猜我们应该倾向于为 UITableView
使用的数据模型数组使用不可变数组。关于这个的阅读在互联网上非常不同。我会说这可以防止在 tableview 显示数据时修改数组。例如,如果发生上述情况,numberOfRowsInSection:
方法可能会出现问题,对吧(即使我知道这在理论上是可能的,但我仍然无法真正想到这种情况如何在现实世界中发生)?
现在,在 commitEditingStyle:forRowAtIndexPath:
方法中,我正在这样做(messagesArray 是可变的):
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
Message *message = messageArray[indexPath.row];
[messagesArray removeObject:message];
[self.messageTable deleteRowsAtIndexPaths:[NSArray arrayWithObject: indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
而不是(messagesArray
不可变):
NSMutableArray *temp = [NSMutableArray arrayWithArray:messagesArray];
[temp removeObject:message];
messagesArray = [NSArray arrayWithArray:temp];
如果 messageArray
是不可变的,则后一个代码是我必须做的。
现在我有两个问题...IMO(如果我错了请纠正我),在上面的方法中以两种方式从数组中删除一个对象具有相同的效果。 messagesArray 最终删除了一个元素。就是这样......但是像后面的例子那样做,让我拥有不可变的数据模型数组。
有人可以评论在删除单元格后更新数据模型数组的实际首选方式(或者我可以说正确的方式吗?)?
我更愿意有一个 mutable 数组,但将其设为私有。然后,如果另一个 class 需要更改数组,您可以提供一个 add()
方法和一个 delete()
方法。两者都将负责更新数组和 table 视图。
从 table 视图的角度来看,您的数据源使用什么结构来组织数据并不重要。 table 视图不直接访问该结构。它在需要时向数据源询问它需要的部分。
现在,您是对的:您可以通过更改支持数据来搞砸您的 table 视图。但无论特定集合的可变性如何,都会发生这种情况。你的 immutable 数组片段做同样的事情:table 视图不知道有什么改变,直到你用 deleteRowsAtIndexPaths:animated
通知 它。在数据源更新时重新加载 table 视图是 必不可少的,无论您的数据源在内部做什么。
Swift 3 版本:
func tableView(_ tableView: UITableView, commit editingStyle:
UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
//1. remove data from model
dataSource.remove(at: indexPath.row)
//2. remove row from view
tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)
}
}
是的!实现滑动删除时不需要重新加载数据! UITableView
处理它。你只需要更新你的数据源