我正在开发一个供稿阅读器iOS项目。 Feed条目按反向时间顺序列在UITableView
中。在启动时,它们从数据库加载到数组中。
当应用程序同步到供稿时,它会为新订单创建新数组,然后更新表格,将新数组与旧数组进行比较,以确定要删除,更新或插入的单元格。我完成它的方式是天真的,因此效率非常低:很多调用indexOfObject:
来查看一个数组中的项是否在另一个数组中。两次。对于每个新条目添加到新数组中的一次,查看它是否在旧数组中,然后对旧数组中的每个条目执行一次,以查看新数组中的不是。
作为一名数据库专家,这个设计让我感到不快。
但它必须是一种非常常见的模式。什么是最合适,最充分的Cocoa-ish方式呢?
答案 0 :(得分:4)
原来我错了。我找到的解决方案是像往常一样在数组中添加和删除项目,然后根据添加,更改或移动的每一行调用insertRowsAtIndexPaths:withRowAnimation:
,reloadRowsAtIndexPaths:withRowAnimation:
和deleteRowsAtIndexPaths:withRowAnimation:
。我之前计划中的错误是我应该等到所有更改完成后再进行,然后在beginUpdates
/ endUpdates
块中只调用一次这些方法。事实证明这个块实际上并不是必需的,因为可以在它们之外调用修改方法。
为每个插入,更新或删除的单元格调用每个方法要比在最后计算所有更改并立即提交它们容易得多。只是太混乱,容易出错,并且无法一次性完成所有操作。
所以我最终得到的代码看起来像这样:
if (parsedItem.savedState == ItemModelSavedStateInserted) {
// It's a new entry. Insert it.
[items addObject:parsedItem];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
} else {
// It's an existing entry. Find it in the portal and move it, if necessary.
NSUInteger foundAt = [items
indexOfObject:parsedItem
inRange:NSMakeRange(currentItemIndex, items.count - currentItemIndex - 1)
];
if (foundAt == currentItemIndex) {
// It hasn't moved!
if (parsedItem.savedState == ItemModelSavedStateUpdated) {
// It was updated, so replace it.
[items replaceObjectAtIndex:currentItemIndex withObject:parsedItem];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:currentItemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationMiddle];
}
} else {
// It has shifted position.
if (foundAt != NSNotFound) {
// It has moved.
[items removeObjectAtIndex:foundAt];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:foundAt inSection:0]] withRowAnimation:UITableViewRowAnimationBottom];
}
// Need to insert it.
[items insertObject:parsedItem atIndex:currentItemIndex];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:currentItemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
}
}
答案 1 :(得分:1)
考虑使用NSSets来区分当前项的集合和新项的集合,使用单个NSMutableArray来保存有序的当前列表。您可能希望从数组中删除每个过期的项目,然后将每个未过期的新项目分别输入到数组中。您既不需要删除也不能分类的项目是您可能想要更新的项目。