Fix background notification processing of CloudKit changes.
This commit is contained in:
parent
850d6b5623
commit
ea78b5683d
|
@ -58,6 +58,8 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
func receiveRemoteNotification(for account: Account, userInfo: [AnyHashable : Any], completion: @escaping () -> Void) {
|
||||
os_log(.debug, log: log, "Processing remote notification...")
|
||||
|
||||
let group = DispatchGroup()
|
||||
|
||||
zones.forEach { zone in
|
||||
|
@ -68,6 +70,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
os_log(.debug, log: self.log, "Done processing remote notification...")
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,14 +48,10 @@ class CloudKitAcountZoneDelegate: CloudKitZoneDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func cloudKitDidChange(records: [CKRecord]) {
|
||||
// We don't batch process these records
|
||||
func cloudKitDidModify(changed: [CKRecord], deleted: [CloudKitRecordKey], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func cloudKitDidDelete(recordKeys: [CloudKitRecordKey]) {
|
||||
// We don't batch process these records
|
||||
}
|
||||
|
||||
func addOrUpdateWebFeed(_ record: CKRecord) {
|
||||
guard let account = account,
|
||||
let urlString = record[CloudKitAccountZone.CloudKitWebFeed.Fields.url] as? String,
|
||||
|
|
|
@ -31,7 +31,8 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
|
|||
// Article downloads clean up old articles and statuses
|
||||
}
|
||||
|
||||
func cloudKitDidChange(records: [CKRecord]) {
|
||||
func cloudKitDidModify(changed: [CKRecord], deleted: [CloudKitRecordKey], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
|
||||
database.selectPendingReadStatusArticleIDs() { result in
|
||||
switch result {
|
||||
case .success(let pendingReadStatusArticleIDs):
|
||||
|
@ -40,9 +41,10 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
|
|||
switch result {
|
||||
case .success(let pendingStarredStatusArticleIDs):
|
||||
|
||||
self.process(records: records,
|
||||
self.process(records: changed,
|
||||
pendingReadStatusArticleIDs: pendingReadStatusArticleIDs,
|
||||
pendingStarredStatusArticleIDs: pendingStarredStatusArticleIDs)
|
||||
pendingStarredStatusArticleIDs: pendingStarredStatusArticleIDs,
|
||||
completion: completion)
|
||||
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error occurred geting pending starred records: %@", error.localizedDescription)
|
||||
|
@ -56,15 +58,11 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
|
|||
|
||||
}
|
||||
|
||||
func cloudKitDidDelete(recordKeys: [CloudKitRecordKey]) {
|
||||
// Article downloads clean up old articles and statuses
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private extension CloudKitArticlesZoneDelegate {
|
||||
|
||||
func process(records: [CKRecord], pendingReadStatusArticleIDs: Set<String>, pendingStarredStatusArticleIDs: Set<String>) {
|
||||
func process(records: [CKRecord], pendingReadStatusArticleIDs: Set<String>, pendingStarredStatusArticleIDs: Set<String>, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
|
||||
let receivedUnreadArticleIDs = Set(records.filter( { $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.read] == "0" }).map({ $0.externalID }))
|
||||
let receivedReadArticleIDs = Set(records.filter( { $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.read] == "1" }).map({ $0.externalID }))
|
||||
|
@ -76,10 +74,31 @@ private extension CloudKitArticlesZoneDelegate {
|
|||
let updateableUnstarredArticleIDs = receivedUnstarredArticleIDs.subtracting(pendingStarredStatusArticleIDs)
|
||||
let updateableStarredArticleIDs = receivedStarredArticleIDs.subtracting(pendingStarredStatusArticleIDs)
|
||||
|
||||
account?.markAsUnread(updateableUnreadArticleIDs)
|
||||
account?.markAsRead(updateableReadArticleIDs)
|
||||
account?.markAsUnstarred(updateableUnstarredArticleIDs)
|
||||
account?.markAsStarred(updateableStarredArticleIDs)
|
||||
let group = DispatchGroup()
|
||||
|
||||
group.enter()
|
||||
account?.markAsUnread(updateableUnreadArticleIDs) { _ in
|
||||
group.leave()
|
||||
}
|
||||
|
||||
group.enter()
|
||||
account?.markAsRead(updateableReadArticleIDs) { _ in
|
||||
group.leave()
|
||||
}
|
||||
|
||||
group.enter()
|
||||
account?.markAsUnstarred(updateableUnstarredArticleIDs) { _ in
|
||||
group.leave()
|
||||
}
|
||||
|
||||
group.enter()
|
||||
account?.markAsStarred(updateableStarredArticleIDs) { _ in
|
||||
group.leave()
|
||||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,7 @@ enum CloudKitZoneError: Error {
|
|||
protocol CloudKitZoneDelegate: class {
|
||||
func cloudKitDidChange(record: CKRecord);
|
||||
func cloudKitDidDelete(recordKey: CloudKitRecordKey)
|
||||
func cloudKitDidChange(records: [CKRecord]);
|
||||
func cloudKitDidDelete(recordKeys: [CloudKitRecordKey])
|
||||
func cloudKitDidModify(changed: [CKRecord], deleted: [CloudKitRecordKey], completion: @escaping (Result<Void, Error>) -> Void);
|
||||
}
|
||||
|
||||
typealias CloudKitRecordKey = (recordType: CKRecord.RecordType, recordID: CKRecord.ID)
|
||||
|
@ -326,9 +325,7 @@ extension CloudKitZone {
|
|||
case .success:
|
||||
DispatchQueue.main.async {
|
||||
self.refreshProgress?.completeTask()
|
||||
self.delegate?.cloudKitDidChange(records: changedRecords)
|
||||
self.delegate?.cloudKitDidDelete(recordKeys: deletedRecordKeys)
|
||||
completion(.success(()))
|
||||
self.delegate?.cloudKitDidModify(changed: changedRecords, deleted: deletedRecordKeys, completion: completion)
|
||||
}
|
||||
case .zoneNotFound:
|
||||
self.createZoneRecord() { result in
|
||||
|
|
|
@ -112,7 +112,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|||
|
||||
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
self.resumeDatabaseProcessingIfNecessary()
|
||||
AccountManager.shared.receiveRemoteNotification(userInfo: userInfo) {
|
||||
self.suspendApplication()
|
||||
completionHandler(.newData)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue