Search code examples
iosswiftcloudkit

How to delete a subscription in CloudKit


I want to delete a specific subscription, but I'm not sure how to obtain the subscription ID. There are a few options to delete a subscription, all of which requires knowing the subscription ID in advance:

  1. delete(withSubscriptionID:completionHandler:)

Example:

let database = CKContainer.default().publicCloudDatabase
database.delete(withSubscriptionID: subscription.subscriptionID) { (result, error) in
   // completed 
}
  1. fetchAllSubscriptions(completionHandler:)

Example:

let database = CKContainer.default().publicCloudDatabase
database.fetchAllSubscriptions { subscriptions, error in
    if error == nil {
        if let subscriptions = subscriptions {
            // find the subscription ID of my choice and use the method from #1 to delete
        }
    } else {
        print(error!.localizedDescription)
    }
}
  1. CKModifySubscriptionsOperation

Example:

let operation = CKModifySubscriptionsOperation(subscriptionsToSave: [], subscriptionIDsToDelete: [subscriptionID])
operation.modifySubscriptionsCompletionBlock =  {
    (modifiedSubscriptions: [CKSubscription]?, deletedSubscriptionIDs: [String]?, error: Error?) -> Void in

    if error != nil {
        print(error!.localizedDescription)
    } else {
        print("Success!")
    }
}
operation.qualityOfService = .utility
privateDatabase.add(operation)

For saving and deleting Core Data records, you can use recordName to get the CKRecord ID, which is easier to save in Core Data:

let recordID = CKRecord.ID(recordName: recordName)

Is there something similar for subscriptions or do I necessarily have to save the subscription ID at the time I create it? It looks like CKQuerySubscription doesn't even have recordName:

[<CKQuerySubscription: 0x283a3be40; ; Query Subscription: recordType=Progress, predicate=userId == "_sdfd1cedfea6965asdfdsc58e3d", subscriptionOptions=1, subscriptionID=SDF23BB6B-2C15-4F4D-BE7F-DF234GS, zoneID=(null)>
{
    alertBody -> New Post!
    alertLocalizationKey -> "(null)
    alertLocalizationArgs -> []
    title -> My App
    titleLocalizationKey -> "(null)
    titleLocalizationArgs -> []
    subtitle -> (null)
    subtitleLocalizationKey -> "(null)
    subtitleLocalizationArgs -> []
    alertActionLocalizationKey -> (null)
    alertLaunchImage -> (null)
    soundName -> default
    desiredKeys -> []
    shouldBadge -> NO
    shouldSendContentAvailable -> NO
    shouldSendMutableContent -> NO
    category -> (null)
    collapseIDKey -> (null)

}])

Solution

  • How are you creating the CKQuerySubscriptions to begin with? You specify an ID for it when you create it and that's how you know what the subscriptionID is:

    let subscriptionWorkspace = CKQuerySubscription(
      recordType: "YourRecordType",
      predicate: ...,
      subscriptionID: "Your-ID-Goes-Here",
      options: [...]
    )
    

    If you are creating subscriptions to individual CKRecords then you can create a subscriptionID like:

    "YourRecordType|\(recordName)"
    

    There are usually better ways of subscribing to entire record types with predicate conditions than subscribing to a record at a time, though.

    If you want further help, please add more detail about the creation of your CKQuerySubscriptions.