diff --git a/Tusker/CoreData/MastodonCachePersistentStore.swift b/Tusker/CoreData/MastodonCachePersistentStore.swift index b437deda..fc6b80e9 100644 --- a/Tusker/CoreData/MastodonCachePersistentStore.swift +++ b/Tusker/CoreData/MastodonCachePersistentStore.swift @@ -78,8 +78,8 @@ class MastodonCachePersistentStore: NSPersistentContainer { if self.backgroundContext.hasChanges { try! self.backgroundContext.save() } - completion?() statuses.forEach { self.statusSubject.send($0.id) } + completion?() } } @@ -142,4 +142,27 @@ class MastodonCachePersistentStore: NSPersistentContainer { } } + func performBatchUpdates(_ block: @escaping (_ context: NSManagedObjectContext, _ addAccounts: ([Account]) -> Void, _ addStatuses: ([Status]) -> Void) -> Void, completion: (() -> Void)? = nil) { + backgroundContext.perform { + var updatedAccounts = [String]() + var updatedStatuses = [String]() + + block(self.backgroundContext, { (accounts) in + accounts.forEach { self.upsert(account: $0) } + updatedAccounts.append(contentsOf: accounts.map { $0.id }) + }, { (statuses) in + statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true) } + updatedStatuses.append(contentsOf: statuses.map { $0.id }) + }) + + updatedAccounts.forEach(self.accountSubject.send) + updatedStatuses.forEach(self.statusSubject.send) + + if self.backgroundContext.hasChanges { + try! self.backgroundContext.save() + } + completion?() + } + } + } diff --git a/Tusker/Screens/Search/SearchResultsViewController.swift b/Tusker/Screens/Search/SearchResultsViewController.swift index 4cc83297..dad9e1ad 100644 --- a/Tusker/Screens/Search/SearchResultsViewController.swift +++ b/Tusker/Screens/Search/SearchResultsViewController.swift @@ -116,10 +116,8 @@ class SearchResultsViewController: EnhancedTableViewController { } self.currentQuery = query - if self.dataSource.snapshot().numberOfItems == 0 { - activityIndicator.isHidden = false - activityIndicator.startAnimating() - } + activityIndicator.isHidden = false + activityIndicator.startAnimating() let request = Client.search(query: query, resolve: true, limit: 10) mastodonController.run(request) { (response) in @@ -131,24 +129,42 @@ class SearchResultsViewController: EnhancedTableViewController { } guard self.currentQuery == query else { return } - + + let oldSnapshot = self.dataSource.snapshot() var snapshot = NSDiffableDataSourceSnapshot() - if self.onlySections.contains(.accounts) && !results.accounts.isEmpty { - snapshot.appendSections([.accounts]) - snapshot.appendItems(results.accounts.map { .account($0.id) }, toSection: .accounts) - self.mastodonController.persistentContainer.addAll(accounts: results.accounts) - } - if self.onlySections.contains(.hashtags) && !results.hashtags.isEmpty { - snapshot.appendSections([.hashtags]) - snapshot.appendItems(results.hashtags.map { .hashtag($0) }, toSection: .hashtags) - } - if self.onlySections.contains(.statuses) && !results.statuses.isEmpty { - snapshot.appendSections([.statuses]) - snapshot.appendItems(results.statuses.map { .status($0.id, .unknown) }, toSection: .statuses) - self.mastodonController.persistentContainer.addAll(statuses: results.statuses) - self.mastodonController.persistentContainer.addAll(accounts: results.statuses.map { $0.account }) - } - self.dataSource.apply(snapshot) + + self.mastodonController.persistentContainer.performBatchUpdates({ (context, addAccounts, addStatuses) in + // todo: reference count accounts +// oldSnapshot.itemIdentifiers(inSection: .accounts).forEach { (item) in +// guard case let .account(id) = item else { return } +// self.mastodonController.persistentContainer.account(for: id, in: context)?.decrementReferenceCount() +// } + + oldSnapshot.itemIdentifiers(inSection: .statuses).forEach { (item) in + guard case let .status(id, _) = item else { return } + self.mastodonController.persistentContainer.status(for: id, in: context)?.decrementReferenceCount() + } + + if self.onlySections.contains(.accounts) && !results.accounts.isEmpty { + snapshot.appendSections([.accounts]) + snapshot.appendItems(results.accounts.map { .account($0.id) }, toSection: .accounts) + addAccounts(results.accounts) + } + if self.onlySections.contains(.hashtags) && !results.hashtags.isEmpty { + snapshot.appendSections([.hashtags]) + snapshot.appendItems(results.hashtags.map { .hashtag($0) }, toSection: .hashtags) + } + if self.onlySections.contains(.statuses) && !results.statuses.isEmpty { + snapshot.appendSections([.statuses]) + snapshot.appendItems(results.statuses.map { .status($0.id, .unknown) }, toSection: .statuses) + addStatuses(results.statuses) + addAccounts(results.statuses.map { $0.account }) + } + }, completion: { + DispatchQueue.main.async { + self.dataSource.apply(snapshot) + } + }) } }