From 5027660b52a2fe749f1c44ca6a2d2c4cb63e0390 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 31 Dec 2022 16:57:13 -0500 Subject: [PATCH] Maybe fix crash when restoring unloaded statuses due to race condition --- Tusker/CoreData/MastodonCachePersistentStore.swift | 13 +++++++------ .../Screens/Timeline/TimelineViewController.swift | 10 ++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Tusker/CoreData/MastodonCachePersistentStore.swift b/Tusker/CoreData/MastodonCachePersistentStore.swift index 93c8deb1..18c8d9fe 100644 --- a/Tusker/CoreData/MastodonCachePersistentStore.swift +++ b/Tusker/CoreData/MastodonCachePersistentStore.swift @@ -256,18 +256,19 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer { return statusMO } - func addAll(statuses: [Status], completion: (() -> Void)? = nil) { - backgroundContext.perform { - statuses.forEach { self.upsert(status: $0, context: self.backgroundContext) } - self.save(context: self.backgroundContext) + func addAll(statuses: [Status], in context: NSManagedObjectContext? = nil, completion: (() -> Void)? = nil) { + let context = context ?? backgroundContext + context.perform { + statuses.forEach { self.upsert(status: $0, context: context) } + self.save(context: context) statuses.forEach { self.statusSubject.send($0.id) } completion?() } } - func addAll(statuses: [Status]) async { + func addAll(statuses: [Status], in context: NSManagedObjectContext? = nil) async { return await withCheckedContinuation { continuation in - addAll(statuses: statuses) { + addAll(statuses: statuses, in: context) { continuation.resume() } } diff --git a/Tusker/Screens/Timeline/TimelineViewController.swift b/Tusker/Screens/Timeline/TimelineViewController.swift index eda5f7cb..adc71df8 100644 --- a/Tusker/Screens/Timeline/TimelineViewController.swift +++ b/Tusker/Screens/Timeline/TimelineViewController.swift @@ -367,17 +367,19 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro } } } - await mastodonController.persistentContainer.addAll(statuses: statuses) + await mastodonController.persistentContainer.addAll(statuses: statuses, in: mastodonController.persistentContainer.viewContext) } private func applyItemsToRestore(position: TimelinePosition) { var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.statuses]) + let statusIDs = position.statusIDs + let centerStatusID = position.centerStatusID let items = position.statusIDs.map { Item.status(id: $0, collapseState: .unknown, filterState: .unknown) } snapshot.appendItems(items, toSection: .statuses) dataSource.apply(snapshot, animatingDifferences: false) { - if let centerID = position.centerStatusID, - let index = position.statusIDs.firstIndex(of: centerID), + if let centerStatusID, + let index = statusIDs.firstIndex(of: centerStatusID), let indexPath = self.dataSource.indexPath(for: items[index]) { // it sometimes takes multiple attempts to convert on the right scroll position // since we're dealing with a bunch of unmeasured cells, so just try a few times in a loop @@ -392,7 +394,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro break } } - stateRestorationLogger.fault("TimelineViewController: restored statuses with center ID \(centerID)") + stateRestorationLogger.fault("TimelineViewController: restored statuses with center ID \(centerStatusID)") } else { stateRestorationLogger.fault("TimelineViewController: restored statuses, but couldn't find center ID") }