Improve scrolling performance with very large timelines. Reload visible cells only, and minimize the amount of looping through articles in the array.

This commit is contained in:
Brent Simmons 2018-09-26 21:33:55 -07:00
parent 9ad468781d
commit 3fdf8b3728
2 changed files with 27 additions and 42 deletions

View File

@ -50,20 +50,6 @@ extension Array where Element == Article {
})
}
func indexesForArticleIDs(_ articleIDs: Set<String>) -> IndexSet {
var indexes = IndexSet()
articleIDs.forEach { (articleID) in
let oneIndex = rowForArticleID(articleID)
if oneIndex != NSNotFound {
indexes.insert(oneIndex)
}
}
return indexes
}
func sortedByDate(_ sortDirection: ComparisonResult) -> ArticleArray {
let articles = sorted { (article1, article2) -> Bool in
@ -118,19 +104,3 @@ extension Array where Element == Article {
}
}
private extension Array where Element == Article {
func rowForArticleID(_ articleID: String) -> Int {
if let index = index(where: { $0.articleID == articleID }) {
return index
}
return NSNotFound
}
func rowForArticle(_ article: Article) -> Int {
return rowForArticleID(article.articleID)
}
}

View File

@ -361,7 +361,7 @@ class TimelineViewController: NSViewController, UndoableCommandRunner {
guard let articles = note.userInfo?[Account.UserInfoKey.articles] as? Set<Article> else {
return
}
reloadCellsForArticleIDs(articles.articleIDs())
reloadVisibleCells(for: articles)
}
@objc func feedIconDidBecomeAvailable(_ note: Notification) {
@ -369,10 +369,15 @@ class TimelineViewController: NSViewController, UndoableCommandRunner {
guard let feed = note.userInfo?[UserInfoKey.feed] as? Feed else {
return
}
let articlesToReload = articles.filter { (article) -> Bool in
let indexesToReload = tableView.indexesOfAvailableRowsPassingTest { (row) -> Bool in
guard let article = articles.articleAtRow(row) else {
return false
}
return feed == article.feed
}
reloadCellsForArticles(articlesToReload)
if let indexesToReload = indexesToReload {
reloadCells(for: indexesToReload)
}
}
@objc func avatarDidBecomeAvailable(_ note: Notification) {
@ -432,22 +437,32 @@ class TimelineViewController: NSViewController, UndoableCommandRunner {
return nil
}
private func reloadCellsForArticles(_ articles: [Article]) {
reloadCellsForArticleIDs(Set(articles.articleIDs()))
private func reloadVisibleCells(for articles: [Article]) {
reloadVisibleCells(for: Set(articles.articleIDs()))
}
private func reloadVisibleCells(for articles: Set<Article>) {
reloadVisibleCells(for: articles.articleIDs())
}
private func reloadCellsForArticleIDs(_ articleIDs: Set<String>) {
private func reloadVisibleCells(for articleIDs: Set<String>) {
if articleIDs.isEmpty {
return
}
let indexes = articles.indexesForArticleIDs(articleIDs)
reloadCells(for: indexes)
let indexes = indexesForArticleIDs(articleIDs)
reloadVisibleCells(for: indexes)
}
private func reloadVisibleCells(for indexes: IndexSet) {
let indexesToReload = tableView.indexesOfAvailableRowsPassingTest { (row) -> Bool in
return indexes.contains(row)
}
if let indexesToReload = indexesToReload {
reloadCells(for: indexesToReload)
}
}
private func reloadCells(for indexes: IndexSet) {
if indexes.isEmpty {
return
}
@ -776,7 +791,7 @@ private extension TimelineViewController {
func selectArticles(_ articleIDs: [String]) {
let indexesToSelect = articles.indexesForArticleIDs(Set(articleIDs))
let indexesToSelect = indexesForArticleIDs(Set(articleIDs))
if indexesToSelect.isEmpty {
tableView.deselectAll(self)
return