Add user web feed subscription management.
This commit is contained in:
parent
231e3a12e2
commit
3a228be142
@ -60,7 +60,7 @@
|
|||||||
519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */; };
|
519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */; };
|
||||||
519E84A82434C5EF00D238B0 /* CloudKitArticlesZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */; };
|
519E84A82434C5EF00D238B0 /* CloudKitArticlesZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */; };
|
||||||
519E84AC2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */; };
|
519E84AC2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */; };
|
||||||
51B544672438F410003F03BF /* CloudKitContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B544662438F410003F03BF /* CloudKitContainer.swift */; };
|
51B544672438F410003F03BF /* CKContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B544662438F410003F03BF /* CKContainer+Extensions.swift */; };
|
||||||
51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; };
|
51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; };
|
||||||
51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC8FCB237EC055004F8B56 /* Feed.swift */; };
|
51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC8FCB237EC055004F8B56 /* Feed.swift */; };
|
||||||
51BFDECE238B508D00216323 /* ContainerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */; };
|
51BFDECE238B508D00216323 /* ContainerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */; };
|
||||||
@ -298,7 +298,7 @@
|
|||||||
519E84A52433D49000D238B0 /* OPMLNormalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLNormalizer.swift; sourceTree = "<group>"; };
|
519E84A52433D49000D238B0 /* OPMLNormalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLNormalizer.swift; sourceTree = "<group>"; };
|
||||||
519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZone.swift; sourceTree = "<group>"; };
|
519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZone.swift; sourceTree = "<group>"; };
|
||||||
519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZoneDelegate.swift; sourceTree = "<group>"; };
|
519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZoneDelegate.swift; sourceTree = "<group>"; };
|
||||||
51B544662438F410003F03BF /* CloudKitContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitContainer.swift; sourceTree = "<group>"; };
|
51B544662438F410003F03BF /* CKContainer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CKContainer+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = "<group>"; };
|
51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = "<group>"; };
|
||||||
51BC8FCB237EC055004F8B56 /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; };
|
51BC8FCB237EC055004F8B56 /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; };
|
||||||
51BFDECD238B508D00216323 /* ContainerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerIdentifier.swift; sourceTree = "<group>"; };
|
51BFDECD238B508D00216323 /* ContainerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerIdentifier.swift; sourceTree = "<group>"; };
|
||||||
@ -525,13 +525,13 @@
|
|||||||
5103A9D7242253DC00410853 /* CloudKit */ = {
|
5103A9D7242253DC00410853 /* CloudKit */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
51B544662438F410003F03BF /* CKContainer+Extensions.swift */,
|
||||||
512DD4CA2431000600C17B1F /* CKRecord+Extensions.swift */,
|
512DD4CA2431000600C17B1F /* CKRecord+Extensions.swift */,
|
||||||
5103A9D82422546800410853 /* CloudKitAccountDelegate.swift */,
|
5103A9D82422546800410853 /* CloudKitAccountDelegate.swift */,
|
||||||
51E4DB2F2426353D0091EB5B /* CloudKitAccountZone.swift */,
|
51E4DB2F2426353D0091EB5B /* CloudKitAccountZone.swift */,
|
||||||
512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */,
|
512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */,
|
||||||
519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */,
|
519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */,
|
||||||
519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */,
|
519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */,
|
||||||
51B544662438F410003F03BF /* CloudKitContainer.swift */,
|
|
||||||
5150FFFD243823B800C1A442 /* CloudKitError.swift */,
|
5150FFFD243823B800C1A442 /* CloudKitError.swift */,
|
||||||
5150FFFF2438682300C1A442 /* CloudKitPublicZone.swift */,
|
5150FFFF2438682300C1A442 /* CloudKitPublicZone.swift */,
|
||||||
51E4DB2D242633ED0091EB5B /* CloudKitZone.swift */,
|
51E4DB2D242633ED0091EB5B /* CloudKitZone.swift */,
|
||||||
@ -1159,7 +1159,7 @@
|
|||||||
84B99C9F1FAE8D3200ECDEDB /* ContainerPath.swift in Sources */,
|
84B99C9F1FAE8D3200ECDEDB /* ContainerPath.swift in Sources */,
|
||||||
51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */,
|
51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */,
|
||||||
846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */,
|
846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */,
|
||||||
51B544672438F410003F03BF /* CloudKitContainer.swift in Sources */,
|
51B544672438F410003F03BF /* CKContainer+Extensions.swift in Sources */,
|
||||||
9EA643CF2391D3560018A28C /* FeedlyAddExistingFeedOperation.swift in Sources */,
|
9EA643CF2391D3560018A28C /* FeedlyAddExistingFeedOperation.swift in Sources */,
|
||||||
55203300229D5D5A009559E0 /* ReaderAPICaller.swift in Sources */,
|
55203300229D5D5A009559E0 /* ReaderAPICaller.swift in Sources */,
|
||||||
9E1D154F233371DD00F4944C /* FeedlyGetCollectionsOperation.swift in Sources */,
|
9E1D154F233371DD00F4944C /* FeedlyGetCollectionsOperation.swift in Sources */,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// CloudKitContainer.swift
|
// CKContainer+Extensions.swift
|
||||||
// Account
|
// Account
|
||||||
//
|
//
|
||||||
// Created by Maurice Parker on 4/4/20.
|
// Created by Maurice Parker on 4/4/20.
|
||||||
@ -9,11 +9,11 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import CloudKit
|
import CloudKit
|
||||||
|
|
||||||
struct CloudKitContainer {
|
extension CKContainer {
|
||||||
|
|
||||||
private static let userRecordIDKey = "cloudkit.server.userRecordID"
|
private static let userRecordIDKey = "cloudkit.server.userRecordID"
|
||||||
|
|
||||||
static var userRecordID: String? {
|
var userRecordID: String? {
|
||||||
get {
|
get {
|
||||||
return UserDefaults.standard.string(forKey: Self.userRecordIDKey)
|
return UserDefaults.standard.string(forKey: Self.userRecordIDKey)
|
||||||
}
|
}
|
||||||
@ -26,13 +26,13 @@ struct CloudKitContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func fetchUserRecordID() {
|
func fetchUserRecordID() {
|
||||||
guard Self.userRecordID == nil else { return }
|
guard userRecordID == nil else { return }
|
||||||
CKContainer.default().fetchUserRecordID { recordID, error in
|
fetchUserRecordID { recordID, error in
|
||||||
guard let recordID = recordID, error == nil else {
|
guard let recordID = recordID, error == nil else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Self.userRecordID = recordID.recordName
|
self.userRecordID = recordID.recordName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +219,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||||||
self.publicZone.createSubscription(feed) { result in
|
self.publicZone.createSubscription(feed) { result in
|
||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
if case .failure(let error) = result {
|
if case .failure(let error) = result {
|
||||||
os_log(.error, log: self.log, "Restore folder feed error: %@.", error.localizedDescription)
|
os_log(.error, log: self.log, "An error occurred while creating the subscription: %@.", error.localizedDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||||||
|
|
||||||
// Check to see if this is a new account and initialize anything we need
|
// Check to see if this is a new account and initialize anything we need
|
||||||
if account.externalID == nil {
|
if account.externalID == nil {
|
||||||
CloudKitContainer.fetchUserRecordID()
|
container.fetchUserRecordID()
|
||||||
accountZone.findOrCreateAccount() { result in
|
accountZone.findOrCreateAccount() { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let externalID):
|
case .success(let externalID):
|
||||||
|
@ -25,7 +25,7 @@ final class CloudKitAccountZone: CloudKitZone {
|
|||||||
var delegate: CloudKitZoneDelegate?
|
var delegate: CloudKitZoneDelegate?
|
||||||
|
|
||||||
struct CloudKitWebFeed {
|
struct CloudKitWebFeed {
|
||||||
static let recordType = "WebFeed"
|
static let recordType = "AccountWebFeed"
|
||||||
struct Fields {
|
struct Fields {
|
||||||
static let url = "url"
|
static let url = "url"
|
||||||
static let editedName = "editedName"
|
static let editedName = "editedName"
|
||||||
@ -34,7 +34,7 @@ final class CloudKitAccountZone: CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct CloudKitContainer {
|
struct CloudKitContainer {
|
||||||
static let recordType = "Container"
|
static let recordType = "AccountContainer"
|
||||||
struct Fields {
|
struct Fields {
|
||||||
static let isAccount = "isAccount"
|
static let isAccount = "isAccount"
|
||||||
static let name = "name"
|
static let name = "name"
|
||||||
@ -77,7 +77,7 @@ final class CloudKitAccountZone: CloudKitZone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
|
save(records, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Persist a web feed record to iCloud and return the external key
|
/// Persist a web feed record to iCloud and return the external key
|
||||||
|
@ -31,7 +31,7 @@ final class CloudKitPublicZone: CloudKitZone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CloudKitUserWebFeedCheck {
|
struct CloudKitWebFeedCheck {
|
||||||
static let recordType = "WebFeedCheck"
|
static let recordType = "WebFeedCheck"
|
||||||
struct Fields {
|
struct Fields {
|
||||||
static let webFeed = "webFeed"
|
static let webFeed = "webFeed"
|
||||||
@ -59,15 +59,10 @@ final class CloudKitPublicZone: CloudKitZone {
|
|||||||
completion()
|
completion()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a CloudKit subscription for the webfeed and any other supporting records that we need
|
||||||
func createSubscription(_ webFeed: WebFeed, completion: @escaping (Result<Void, Error>) -> Void) {
|
func createSubscription(_ webFeed: WebFeed, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
let webFeedRecordID = CKRecord.ID(recordName: webFeed.url.md5String, zoneID: Self.zoneID)
|
|
||||||
let webFeedRecord = CKRecord(recordType: CloudKitWebFeed.recordType, recordID: webFeedRecordID)
|
|
||||||
|
|
||||||
save(webFeedRecord) { result in
|
func createSubscription(_ webFeedRecordRef: CKRecord.Reference) {
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
|
|
||||||
let webFeedRecordRef = CKRecord.Reference(recordID: webFeedRecordID, action: .none)
|
|
||||||
let predicate = NSPredicate(format: "webFeed = %@", webFeedRecordRef)
|
let predicate = NSPredicate(format: "webFeed = %@", webFeedRecordRef)
|
||||||
let subscription = CKQuerySubscription(recordType: CloudKitWebFeed.recordType, predicate: predicate, options: [.firesOnRecordUpdate])
|
let subscription = CKQuerySubscription(recordType: CloudKitWebFeed.recordType, predicate: predicate, options: [.firesOnRecordUpdate])
|
||||||
|
|
||||||
@ -81,7 +76,7 @@ final class CloudKitPublicZone: CloudKitZone {
|
|||||||
case .success(let subscription):
|
case .success(let subscription):
|
||||||
|
|
||||||
let userSubscriptionRecord = CKRecord(recordType: CloudKitUserSubscription.recordType, recordID: self.generateRecordID())
|
let userSubscriptionRecord = CKRecord(recordType: CloudKitUserSubscription.recordType, recordID: self.generateRecordID())
|
||||||
userSubscriptionRecord[CloudKitUserSubscription.Fields.userRecordID] = CloudKitContainer.userRecordID
|
userSubscriptionRecord[CloudKitUserSubscription.Fields.userRecordID] = self.container?.userRecordID
|
||||||
userSubscriptionRecord[CloudKitUserSubscription.Fields.webFeed] = webFeedRecordRef
|
userSubscriptionRecord[CloudKitUserSubscription.Fields.webFeed] = webFeedRecordRef
|
||||||
userSubscriptionRecord[CloudKitUserSubscription.Fields.subscriptionID] = subscription.subscriptionID
|
userSubscriptionRecord[CloudKitUserSubscription.Fields.subscriptionID] = subscription.subscriptionID
|
||||||
|
|
||||||
@ -91,23 +86,52 @@ final class CloudKitPublicZone: CloudKitZone {
|
|||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(externalID: webFeed.url.md5String) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let record):
|
||||||
|
|
||||||
|
let webFeedRecordRef = CKRecord.Reference(record: record, action: .none)
|
||||||
|
createSubscription(webFeedRecordRef)
|
||||||
|
|
||||||
|
case .failure:
|
||||||
|
|
||||||
|
let webFeedRecordID = CKRecord.ID(recordName: webFeed.url.md5String, zoneID: Self.zoneID)
|
||||||
|
let webFeedRecordRef = CKRecord.Reference(recordID: webFeedRecordID, action: .none)
|
||||||
|
let webFeedRecord = CKRecord(recordType: CloudKitWebFeed.recordType, recordID: webFeedRecordID)
|
||||||
|
webFeedRecord[CloudKitWebFeed.Fields.url] = webFeed.url
|
||||||
|
webFeedRecord[CloudKitWebFeed.Fields.httpLastModified] = ""
|
||||||
|
webFeedRecord[CloudKitWebFeed.Fields.httpEtag] = ""
|
||||||
|
|
||||||
|
let webFeedCheckRecord = CKRecord(recordType: CloudKitWebFeedCheck.recordType, recordID: self.generateRecordID())
|
||||||
|
webFeedRecord[CloudKitWebFeedCheck.Fields.webFeed] = webFeedRecordRef
|
||||||
|
webFeedRecord[CloudKitWebFeedCheck.Fields.lastCheck] = Date.distantPast
|
||||||
|
|
||||||
|
self.save([webFeedRecord, webFeedCheckRecord]) { result in
|
||||||
|
switch result {
|
||||||
|
case .success:
|
||||||
|
createSubscription(webFeedRecordRef)
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the subscription for the given feed along with its supporting record
|
/// Remove the subscription for the given feed along with its supporting record
|
||||||
func removeSubscription(_ webFeed: WebFeed, completion: @escaping (Result<Void, Error>) -> Void) {
|
func removeSubscription(_ webFeed: WebFeed, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
guard let userRecordID = CloudKitContainer.userRecordID else {
|
guard let userRecordID = self.container?.userRecordID else {
|
||||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let webFeedRecordID = CKRecord.ID(recordName: webFeed.url.md5String, zoneID: Self.zoneID)
|
let webFeedRecordID = CKRecord.ID(recordName: webFeed.url.md5String, zoneID: Self.zoneID)
|
||||||
let webFeedRecordRef = CKRecord.Reference(recordID: webFeedRecordID, action: .none)
|
let webFeedRecordRef = CKRecord.Reference(recordID: webFeedRecordID, action: .none)
|
||||||
let predicate = NSPredicate(format: "user = %@ AND webFeed = %@", userRecordID, webFeedRecordRef)
|
let predicate = NSPredicate(format: "userRecordID = %@ AND webFeed = %@", userRecordID, webFeedRecordRef)
|
||||||
let ckQuery = CKQuery(recordType: CloudKitUserSubscription.recordType, predicate: predicate)
|
let ckQuery = CKQuery(recordType: CloudKitUserSubscription.recordType, predicate: predicate)
|
||||||
|
|
||||||
query(ckQuery) { result in
|
query(ckQuery) { result in
|
||||||
@ -125,7 +149,8 @@ final class CloudKitPublicZone: CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
completion(.failure(CloudKitZoneError.unknown))
|
os_log(.error, log: self.log, "Remove subscription error. The subscription wasn't found.")
|
||||||
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
@ -10,10 +10,14 @@ import CloudKit
|
|||||||
import os.log
|
import os.log
|
||||||
import RSWeb
|
import RSWeb
|
||||||
|
|
||||||
enum CloudKitZoneError: Error {
|
enum CloudKitZoneError: LocalizedError {
|
||||||
case userDeletedZone
|
case userDeletedZone
|
||||||
case invalidParameter
|
case invalidParameter
|
||||||
case unknown
|
case unknown
|
||||||
|
|
||||||
|
var errorDescription: String? {
|
||||||
|
return NSLocalizedString("An unexpected CloudKit error occurred.", comment: "An unexpected CloudKit error occurred.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol CloudKitZoneDelegate: class {
|
protocol CloudKitZoneDelegate: class {
|
||||||
@ -191,21 +195,41 @@ extension CloudKitZone {
|
|||||||
modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion)
|
modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Save the CKRecords
|
||||||
|
func save(_ records: [CKRecord], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
|
||||||
|
}
|
||||||
|
|
||||||
/// Save the CKSubscription
|
/// Save the CKSubscription
|
||||||
func save(_ subscription: CKSubscription, completion: @escaping (Result<CKSubscription, Error>) -> Void) {
|
func save(_ subscription: CKSubscription, completion: @escaping (Result<CKSubscription, Error>) -> Void) {
|
||||||
database?.save(subscription) { savedSubscription, error in
|
database?.save(subscription) { savedSubscription, error in
|
||||||
switch CloudKitZoneResult.resolve(error) {
|
switch CloudKitZoneResult.resolve(error) {
|
||||||
case .success:
|
case .success:
|
||||||
|
DispatchQueue.main.async {
|
||||||
completion(.success((savedSubscription!)))
|
completion(.success((savedSubscription!)))
|
||||||
|
}
|
||||||
|
case .zoneNotFound:
|
||||||
|
self.createZoneRecord() { result in
|
||||||
|
switch result {
|
||||||
|
case .success:
|
||||||
|
self.save(subscription, completion: completion)
|
||||||
|
case .failure(let error):
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
completion(.failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case .retry(let timeToWait):
|
case .retry(let timeToWait):
|
||||||
self.retryIfPossible(after: timeToWait) {
|
self.retryIfPossible(after: timeToWait) {
|
||||||
self.save(subscription, completion: completion)
|
self.save(subscription, completion: completion)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
DispatchQueue.main.async {
|
||||||
completion(.failure(CloudKitError(error!)))
|
completion(.failure(CloudKitError(error!)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Delete a CKRecord using its recordID
|
/// Delete a CKRecord using its recordID
|
||||||
func delete(recordID: CKRecord.ID, completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(recordID: CKRecord.ID, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
@ -228,16 +252,20 @@ extension CloudKitZone {
|
|||||||
database?.delete(withSubscriptionID: subscriptionID) { _, error in
|
database?.delete(withSubscriptionID: subscriptionID) { _, error in
|
||||||
switch CloudKitZoneResult.resolve(error) {
|
switch CloudKitZoneResult.resolve(error) {
|
||||||
case .success:
|
case .success:
|
||||||
|
DispatchQueue.main.async {
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
|
}
|
||||||
case .retry(let timeToWait):
|
case .retry(let timeToWait):
|
||||||
self.retryIfPossible(after: timeToWait) {
|
self.retryIfPossible(after: timeToWait) {
|
||||||
self.delete(subscriptionID: subscriptionID, completion: completion)
|
self.delete(subscriptionID: subscriptionID, completion: completion)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
DispatchQueue.main.async {
|
||||||
completion(.failure(CloudKitError(error!)))
|
completion(.failure(CloudKitError(error!)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Modify and delete the supplied CKRecords and CKRecord.IDs
|
/// Modify and delete the supplied CKRecords and CKRecord.IDs
|
||||||
func modify(recordsToSave: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping (Result<Void, Error>) -> Void) {
|
func modify(recordsToSave: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user