基于来自服务器和本地的数据集更新TableView



我有一个tableView,它显示所有的新闻,然后如果任何新闻得到更新或新新闻被添加,我检查和更新如下。我想知道如果我的方法是正确的,也在寻找更好的选择(tableviewdiffsource?)

当前用户按此顺序看到以下4条新闻

[n1, n2, n3, n4]

当用户拉刷新时,他从服务器得到3条新闻:[n4, n5, n6]

现在我应该按这个顺序显示新闻[n4, n5, n6, n1, n2, n3]

var allNews = [News]()
func didFetchNews(newNews:[News]) {
var news:[News] = newNews
var newsSet = Set(newNews)
var deletedPaths = [IndexPath]()
for i in 0..<allNews.count {
let news = allNews[i];
if !newsSet.contains(news) {
news.append(news)
} else {
deletedPaths.append(IndexPath(row: i, section: 0))
}
}
var insertedPath = [IndexPath]()
for i in 0..<newNews.count {
insertedPath.append(IndexPath(row: i, section: 0))
}
self.tableView.beginUpdates()
self.tableView.insertRows(at: insertedPath, with: .automatic)
self.tableView.deleteRows(at: deletedPaths, with: .automatic)
self.tableView.endUpdates()
}

DiffableDataSource可能是最有效的解决方案。

然而,你的代码也可以通过使用更高级的函数,如filtermap来优化。

首先计算更新新闻的索引。由于新条目被插入到顶部,因此插入索引路径等于新条目的索引。

然后在过滤索引处删除项,在索引0处插入新项。reversed()避免超出范围的崩溃。

func didFetchNews(newNews: [News]) {
let deletionIndices = allNews.indices.filter{newNews.contains(allNews[$0])}
let deletionIndexPaths = deletionIndices.map{IndexPath(row: $0, section: 0)}
let insertionIndexPaths = newNews.indices.map{IndexPath(row: $0, section: 0)}

for index in deletionIndices.reversed() { allNews.remove(at: index) }
allNews.insert(contentsOf: newNews, at: 0)
self.tableView.beginUpdates()
self.tableView.insertRows(at: insertionIndexPaths, with: .automatic)
self.tableView.deleteRows(at: deletionIndexPaths, with: .automatic)
self.tableView.endUpdates()
}