Update UI in responds to remote changes of saved hashtags/instances
This commit is contained in:
parent
d13b517128
commit
32be76ebee
|
@ -39,6 +39,9 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
|||
return context
|
||||
}()
|
||||
|
||||
private var remoteChangeHandlerQueue = DispatchQueue(label: "PersistentStore remote changes")
|
||||
private var lastRemoteChangeToken: NSPersistentHistoryToken?
|
||||
|
||||
// TODO: consider sending managed objects through this to avoid re-fetching things unnecessarily
|
||||
// would need to audit existing uses to make sure everything happens on the main thread
|
||||
// and when updating things on the background context would need to switch to main, refetch, and then publish
|
||||
|
@ -63,6 +66,8 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
|||
localStoreLocation.appendPathComponent("\(accountInfo!.persistenceKey)_cache.sqlite", isDirectory: false)
|
||||
let localStoreDescription = NSPersistentStoreDescription(url: localStoreLocation)
|
||||
localStoreDescription.configuration = "Local"
|
||||
localStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
|
||||
localStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
|
||||
|
||||
var cloudStoreLocation = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
|
||||
cloudStoreLocation.appendPathComponent("cloud.sqlite", isDirectory: false)
|
||||
|
@ -71,6 +76,8 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
|||
let options = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.space.vaccor.Tusker")
|
||||
options.databaseScope = .private
|
||||
cloudStoreDescription.cloudKitContainerOptions = options
|
||||
cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
|
||||
cloudStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
|
||||
|
||||
persistentStoreDescriptions = [
|
||||
cloudStoreDescription,
|
||||
|
@ -167,6 +174,7 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
|||
viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(managedObjectsDidChange), name: .NSManagedObjectContextObjectsDidChange, object: viewContext)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(remoteChanges), name: .NSPersistentStoreRemoteChange, object: persistentStoreCoordinator)
|
||||
}
|
||||
|
||||
func save(context: NSManagedObjectContext) {
|
||||
|
@ -475,4 +483,45 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
|||
return changes
|
||||
}
|
||||
|
||||
// the remote change notifications only handle deletes, inserts get handled by the regular managed object did change notifications
|
||||
@objc private func remoteChanges(_ notification: Foundation.Notification) {
|
||||
guard let token = notification.userInfo?[NSPersistentHistoryTokenKey] as? NSPersistentHistoryToken else {
|
||||
return
|
||||
}
|
||||
remoteChangeHandlerQueue.async {
|
||||
defer {
|
||||
self.lastRemoteChangeToken = token
|
||||
}
|
||||
let req = NSPersistentHistoryChangeRequest.fetchHistory(after: self.lastRemoteChangeToken)
|
||||
self.backgroundContext.performAndWait {
|
||||
if let result = try? self.backgroundContext.execute(req) as? NSPersistentHistoryResult,
|
||||
let transactions = result.result as? [NSPersistentHistoryTransaction] {
|
||||
var changes: (hashtags: Bool, instances: Bool) = (false, false)
|
||||
outer: for transaction in transactions {
|
||||
for change in transaction.changes ?? [] {
|
||||
if change.changedObjectID.entity.name == "SavedHashtag" {
|
||||
changes.hashtags = true
|
||||
} else if change.changedObjectID.entity.name == "SavedInstance" {
|
||||
changes.instances = true
|
||||
}
|
||||
if changes.hashtags && changes.instances {
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
if changes.hashtags {
|
||||
DispatchQueue.main.async {
|
||||
NotificationCenter.default.post(name: .savedHashtagsChanged, object: nil)
|
||||
}
|
||||
}
|
||||
if changes.instances {
|
||||
DispatchQueue.main.async {
|
||||
NotificationCenter.default.post(name: .savedInstancesChanged, object: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue