diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index 088b09f1e..b71ebc288 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -57,7 +57,7 @@ 5170743C232AEDB500A461A3 /* OPMLFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5170743B232AEDB500A461A3 /* OPMLFile.swift */; }; 519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */; }; 519E84A82434C5EF00D238B0 /* CloudKitArticlesZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */; }; - 519E84AA2434C60400D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A92434C60400D238B0 /* CloudKitArticlesZoneDelegate.swift */; }; + 519E84AC2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */; }; 51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; }; 51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC8FCB237EC055004F8B56 /* Feed.swift */; }; 51BFDECE238B508D00216323 /* ContainerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */; }; @@ -293,7 +293,7 @@ 518B2EA52351306200400001 /* Account_project_test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_project_test.xcconfig; sourceTree = ""; }; 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLNormalizer.swift; sourceTree = ""; }; 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZone.swift; sourceTree = ""; }; - 519E84A92434C60400D238B0 /* CloudKitArticlesZoneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZoneDelegate.swift; sourceTree = ""; }; + 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZoneDelegate.swift; sourceTree = ""; }; 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = ""; }; 51BC8FCB237EC055004F8B56 /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = ""; }; 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerIdentifier.swift; sourceTree = ""; }; @@ -527,7 +527,7 @@ 51E4DB2F2426353D0091EB5B /* CloudKitAccountZone.swift */, 512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */, 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */, - 519E84A92434C60400D238B0 /* CloudKitArticlesZoneDelegate.swift */, + 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */, 51E4DB2D242633ED0091EB5B /* CloudKitZone.swift */, 51C034DE242D65D20014DC71 /* CloudKitZoneResult.swift */, ); @@ -1091,7 +1091,7 @@ 9EA643D5239306AC0018A28C /* FeedlyFeedsSearchResponse.swift in Sources */, 9EAEC60E2332FEC20085D7C9 /* FeedlyFeed.swift in Sources */, 5144EA4E227B829A00D19003 /* FeedbinAccountDelegate.swift in Sources */, - 519E84AA2434C60400D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */, + 519E84AC2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */, 512DD4CB2431000600C17B1F /* CKRecord+Extensions.swift in Sources */, 3B826DAF2385C81C00FC1ADB /* FeedWranglerGenericResult.swift in Sources */, 9ECC9A85234DC16E009B5144 /* FeedlyAccountDelegateError.swift in Sources */, diff --git a/Frameworks/Account/CloudKit/CloudKitAccountZoneDelegate.swift b/Frameworks/Account/CloudKit/CloudKitAccountZoneDelegate.swift index 62e0a4a22..27056ecd1 100644 --- a/Frameworks/Account/CloudKit/CloudKitAccountZoneDelegate.swift +++ b/Frameworks/Account/CloudKit/CloudKitAccountZoneDelegate.swift @@ -37,16 +37,24 @@ class CloudKitAcountZoneDelegate: CloudKitZoneDelegate { } } - func cloudKitDidDelete(recordType: CKRecord.RecordType, recordID: CKRecord.ID) { - switch recordType { + func cloudKitDidDelete(recordKey: CloudKitRecordKey) { + switch recordKey.recordType { case CloudKitAccountZone.CloudKitWebFeed.recordType: - removeWebFeed(recordID.externalID) + removeWebFeed(recordKey.recordID.externalID) case CloudKitAccountZone.CloudKitContainer.recordType: - removeContainer(recordID.externalID) + removeContainer(recordKey.recordID.externalID) default: - assertionFailure("Unknown record type: \(recordID.externalID)") + assertionFailure("Unknown record type: \(recordKey.recordType)") } } + + func cloudKitDidChange(records: [CKRecord]) { + // We don't batch process these records + } + + func cloudKitDidDelete(recordKeys: [CloudKitRecordKey]) { + // We don't batch process these records + } func addOrUpdateWebFeed(_ record: CKRecord) { guard let account = account, diff --git a/Frameworks/Account/CloudKit/CloudKitArticlesZoneDelegate.swift b/Frameworks/Account/CloudKit/CloudKitArticlesZoneDelegate.swift index 5c6cd8f44..1774ae16f 100644 --- a/Frameworks/Account/CloudKit/CloudKitArticlesZoneDelegate.swift +++ b/Frameworks/Account/CloudKit/CloudKitArticlesZoneDelegate.swift @@ -11,7 +11,7 @@ import os.log import CloudKit class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate { - + private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CloudKit") weak var account: Account? @@ -21,14 +21,18 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate { } func cloudKitDidChange(record: CKRecord) { -// switch record.recordType { -// case CloudKitAccountZone.CloudKitWebFeed.recordType: -// default: -// assertionFailure("Unknown record type: \(record.recordType)") -// } + // Process everything in the batch method } - func cloudKitDidDelete(recordType: CKRecord.RecordType, recordID: CKRecord.ID) { + func cloudKitDidDelete(recordKey: CloudKitRecordKey) { + // Article downloads clean up old articles and statuses + } + + func cloudKitDidChange(records: [CKRecord]) { + // TODO + } + + func cloudKitDidDelete(recordKeys: [CloudKitRecordKey]) { // Article downloads clean up old articles and statuses } diff --git a/Frameworks/Account/CloudKit/CloudKitZone.swift b/Frameworks/Account/CloudKit/CloudKitZone.swift index 2ed4486f2..6814538ae 100644 --- a/Frameworks/Account/CloudKit/CloudKitZone.swift +++ b/Frameworks/Account/CloudKit/CloudKitZone.swift @@ -18,9 +18,13 @@ enum CloudKitZoneError: Error { protocol CloudKitZoneDelegate: class { func cloudKitDidChange(record: CKRecord); - func cloudKitDidDelete(recordType: CKRecord.RecordType, recordID: CKRecord.ID) + func cloudKitDidDelete(recordKey: CloudKitRecordKey) + func cloudKitDidChange(records: [CKRecord]); + func cloudKitDidDelete(recordKeys: [CloudKitRecordKey]) } +typealias CloudKitRecordKey = (recordType: CKRecord.RecordType, recordID: CKRecord.ID) + protocol CloudKitZone: class { static var zoneID: CKRecordZone.ID { get } @@ -241,6 +245,9 @@ extension CloudKitZone { func fetchChangesInZone(completion: @escaping (Result) -> Void) { + var changedRecords = [CKRecord]() + var deletedRecordKeys = [CloudKitRecordKey]() + let zoneConfig = CKFetchRecordZoneChangesOperation.ZoneConfiguration() zoneConfig.previousServerChangeToken = changeToken let op = CKFetchRecordZoneChangesOperation(recordZoneIDs: [Self.zoneID], configurationsByRecordZoneID: [Self.zoneID: zoneConfig]) @@ -248,6 +255,7 @@ extension CloudKitZone { op.recordZoneChangeTokensUpdatedBlock = { [weak self] zoneID, token, _ in guard let self = self else { return } + DispatchQueue.main.async { self.changeToken = token } @@ -255,6 +263,8 @@ extension CloudKitZone { op.recordChangedBlock = { [weak self] record in guard let self = self else { return } + + changedRecords.append(record) DispatchQueue.main.async { self.delegate?.cloudKitDidChange(record: record) } @@ -262,8 +272,12 @@ extension CloudKitZone { op.recordWithIDWasDeletedBlock = { [weak self] recordID, recordType in guard let self = self else { return } + + let recordKey = CloudKitRecordKey(recordType: recordType, recordID: recordID) + deletedRecordKeys.append(recordKey) + DispatchQueue.main.async { - self.delegate?.cloudKitDidDelete(recordType: recordType, recordID: recordID) + self.delegate?.cloudKitDidDelete(recordKey: recordKey) } } @@ -287,6 +301,10 @@ extension CloudKitZone { op.fetchRecordZoneChangesCompletionBlock = { [weak self] error in DispatchQueue.main.async { self?.refreshProgress?.completeTask() + + self?.delegate?.cloudKitDidChange(records: changedRecords) + self?.delegate?.cloudKitDidDelete(recordKeys: deletedRecordKeys) + if let error = error { completion(.failure(error)) } else {