diff --git a/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift b/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift index c138a19bc..a031b820f 100644 --- a/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift @@ -176,8 +176,15 @@ final class CloudKitAccountDelegate: AccountDelegate { } func removeWebFeed(for account: Account, with feed: WebFeed, from container: Container, completion: @escaping (Result) -> Void) { - container.removeWebFeed(feed) - completion(.success(())) + accountZone.removeWebFeed(feed) { result in + switch result { + case .success: + container.removeWebFeed(feed) + completion(.success(())) + case .failure(let error): + completion(.failure(error)) + } + } } func moveWebFeed(for account: Account, with feed: WebFeed, from: Container, to: Container, completion: @escaping (Result) -> Void) { diff --git a/Frameworks/Account/CloudKit/CloudKitAccountZone.swift b/Frameworks/Account/CloudKit/CloudKitAccountZone.swift index e215c734a..fd326f5a4 100644 --- a/Frameworks/Account/CloudKit/CloudKitAccountZone.swift +++ b/Frameworks/Account/CloudKit/CloudKitAccountZone.swift @@ -31,7 +31,7 @@ final class CloudKitAccountZone: CloudKitZone { self.database = container.privateCloudDatabase } - /// Persist a feed record to iCloud and return the external key + /// Persist a web feed record to iCloud and return the external key func createFeed(url: String, editedName: String?, completion: @escaping (Result) -> Void) { let record = CKRecord(recordType: CloudKitWebFeed.recordType, recordID: generateRecordID()) record[CloudKitWebFeed.Fields.url] = url @@ -39,9 +39,23 @@ final class CloudKitAccountZone: CloudKitZone { record[CloudKitWebFeed.Fields.editedName] = editedName } - save(recordToStore: record, completion: completion) + save(record: record) { result in + switch result { + case .success: + completion(.success(record.recordID.recordName)) + case .failure(let error): + completion(.failure(error)) + } + } } + func removeWebFeed(_ webFeed: WebFeed, completion: @escaping (Result) -> Void) { + guard let externalID = webFeed.externalID else { + completion(.failure(CloudKitZoneError.invalidParameter)) + return + } + delete(externalID: externalID, completion: completion) + } // private func fetchChangesInZones(_ callback: ((Error?) -> Void)? = nil) { // let changesOp = CKFetchRecordZoneChangesOperation(recordZoneIDs: zoneIds, optionsByRecordZoneID: zoneIdOptions) // changesOp.fetchAllChanges = true diff --git a/Frameworks/Account/CloudKit/CloudKitZone.swift b/Frameworks/Account/CloudKit/CloudKitZone.swift index af865fbaa..57137a8b9 100644 --- a/Frameworks/Account/CloudKit/CloudKitZone.swift +++ b/Frameworks/Account/CloudKit/CloudKitZone.swift @@ -10,6 +10,7 @@ import CloudKit public enum CloudKitZoneError: Error { case userDeletedZone + case invalidParameter case unknown } @@ -114,21 +115,19 @@ extension CloudKitZone { // }) // } - public func save(recordToStore: CKRecord, completion: @escaping (Result) -> Void) { - modify(recordsToStore: [recordToStore], recordIDsToDelete: []) { result in - switch result { - case .success: - completion(.success(recordToStore.recordID.recordName)) - case .failure(let error): - completion(.failure(error)) - } - } + public func save(record: CKRecord, completion: @escaping (Result) -> Void) { + modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion) } + public func delete(externalID: String, completion: @escaping (Result) -> Void) { + let recordID = CKRecord.ID(recordName: externalID, zoneID: Self.zoneID) + modify(recordsToSave: [], recordIDsToDelete: [recordID], completion: completion) + } + /// Sync local data to CloudKit /// For more about the savePolicy: https://developer.apple.com/documentation/cloudkit/ckrecordsavepolicy - public func modify(recordsToStore: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping (Result) -> Void) { - let op = CKModifyRecordsOperation(recordsToSave: recordsToStore, recordIDsToDelete: recordIDsToDelete) + public func modify(recordsToSave: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping (Result) -> Void) { + let op = CKModifyRecordsOperation(recordsToSave: recordsToSave, recordIDsToDelete: recordIDsToDelete) let config = CKOperation.Configuration() config.isLongLived = true @@ -156,7 +155,7 @@ extension CloudKitZone { self.createZoneRecord() { result in switch result { case .success: - self.modify(recordsToStore: recordsToStore, recordIDsToDelete: recordIDsToDelete, completion: completion) + self.modify(recordsToSave: recordsToSave, recordIDsToDelete: recordIDsToDelete, completion: completion) case .failure(let error): completion(.failure(error)) } @@ -167,14 +166,14 @@ extension CloudKitZone { } case .retry(let timeToWait): self.retryOperationIfPossible(retryAfter: timeToWait) { - self.modify(recordsToStore: recordsToStore, recordIDsToDelete: recordIDsToDelete, completion: completion) + self.modify(recordsToSave: recordsToSave, recordIDsToDelete: recordIDsToDelete, completion: completion) } case .limitExceeded: /// CloudKit says maximum number of items in a single request is 400. /// So I think 300 should be fine by them. - let chunkedRecords = recordsToStore.chunked(into: 300) + let chunkedRecords = recordsToSave.chunked(into: 300) for chunk in chunkedRecords { - self.modify(recordsToStore: chunk, recordIDsToDelete: recordIDsToDelete, completion: completion) + self.modify(recordsToSave: chunk, recordIDsToDelete: recordIDsToDelete, completion: completion) } default: DispatchQueue.main.async {