Search code examples
ioscloudkit

CloudKit: delete CKSubscription is not working


Hello i try to cancel a subscription on CloudKit. So far i tried both CKModifySubscriptionsOperation and single removement by publicDB?.deleteSubscriptionWithID. My completionHandler gives me no error and an array of the deleted subscription ID's. So all seems to be ok.

But when i change a record i still get a push notification. How to remove the subscriptions?

Here is the changed code:

func cancelCubscription(subscription:Subscriptions){
    self._animationDelegate?.beginAnimation()
    var subs = [String]()
    subs.append(subscription.daySubSignature!)
    subs.append(subscription.hdpSubSignature!)
    subs.append(subscription.noteSubSignature!)
    subs.append(subscription.planerSubSignature!)
    subs.append(subscription.subjectSubSugnature!)
    subs.append(subscription.teacherSubSignature!)
    subs.append(subscription.tldSubSignature!)

    // Create a CKModifyRecordsOperation operation
    let subscriptionOperation = CKModifySubscriptionsOperation(subscriptionsToSave: nil, subscriptionIDsToDelete: subs)

    subscriptionOperation.modifySubscriptionsCompletionBlock = { (modifiedSubscriptions: [CKSubscription]?, deletedSubscriptionIDs: [String]?, error: NSError?) -> Void in
        guard error==nil else {
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self._animationDelegate?.endAnimation()
                print(error!.localizedDescription)

                let title:String = "Alert_Cancel_CloudKit_Subscription_Error_Title".localized
                let message:String = error!.localizedDescription

                self._alertDelegate?.showAlert(title, message: message)
            })
            return
        }

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self._animationDelegate?.endAnimation()
            print("")
            print("- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *")
            print("Unscribe to CloudKit subscription success!")

            let title:String = "Alert_Cancel_CloudKit_Subscription_Success_Title".localized
            let message:String = "Alert_Cancel_CloudKit_Subscription_Success_Message".localized

            self._alertDelegate?.showAlert(title, message: message)

            for sub in deletedSubscriptionIDs!{
                print("Deleted Subscription: \(sub)")
            }

            subscription.tldSubSignature = "null"
            subscription.daySubSignature = "null"
            subscription.hdpSubSignature = "null"
            subscription.noteSubSignature = "null"
            subscription.planerSubSignature = "null"
            subscription.subjectSubSugnature = "null"
            subscription.teacherSubSignature = "null"
            subscription.subscribed = false
            Subscriptions.editSubsripction(subscription, context: self.appDel.managedObjectContext)
        })
    }

    // Add the operation to an operation queue to execute it
    self._publicDB!.addOperation(subscriptionOperation)
}

my subscriptions are still active: CloudKit Dashboard

my log when subscribing:

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
CloudKit subscription success
teacherSubSignature = DE49AAFB-373C-49E5-8DC8-E81A977E7628
subjectSubSugnature = 3F06E054-D1B9-441E-AED3-CA947820D90C
daySubSignature = 8FF9AC02-F177-4381-AA8D-08AFFDB0A578
hdpSubSignature = 811ABA9A-D31B-4661-B783-B5DF033FC5F4
tldSubSignature = 1C07C661-02A9-48F3-9B92-08F41433E179
planerSubSignature = 1C32F1F0-3647-4F57-BDEF-215A28F69039
hdpSubSignature = 59216B52-1A21-4666-950A-F8CDE44591D2
Subscription Edited in Core Data

and on delete subscription: error = nil

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Unscribe to CloudKit subscription success!

Deleted Subscription: 8FF9AC02-F177-4381-AA8D-08AFFDB0A578
Deleted Subscription: 59216B52-1A21-4666-950A-F8CDE44591D2
Deleted Subscription: 811ABA9A-D31B-4661-B783-B5DF033FC5F4
Deleted Subscription: 1C32F1F0-3647-4F57-BDEF-215A28F69039
Deleted Subscription: 3F06E054-D1B9-441E-AED3-CA947820D90C
Deleted Subscription: DE49AAFB-373C-49E5-8DC8-E81A977E7628
Deleted Subscription: 1C07C661-02A9-48F3-9B92-08F41433E179
Subscription Edited in Core Data

Solution

  • Ok, this isn't the definitive answer, but need to put some code down and the comments are too short. What does it all mean; the first method fetches any outstanding notifications, the second makes sure you the same page as regarding their attention.

    You need to make sure you got something like place before deleting the subscriptions ideally.

    Disclaimer this is demo code; and I haven't tested it extensively. But it should work.

    func fetchSubsInPlace() {
        let container = CKContainer(identifier: "iCloud.ch")
        let publicDB = container.publicCloudDatabase
    
        publicDB.fetchAllSubscriptionsWithCompletionHandler({subscriptions, error in
            for subscriptionObject in subscriptions! {
                let subscription: CKSubscription = subscriptionObject as CKSubscription
                print("subscription \(subscription)")
            }
        })
    }
    
    func fetchNotificationChanges() {
        let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: nil)
    
        var notificationIDsToMarkRead = [CKNotificationID]()
    
        operation.notificationChangedBlock = { (notification: CKNotification) -> Void in
            // Process each notification received
            if notification.notificationType == .Query {
                let queryNotification = notification as! CKQueryNotification
                let reason = queryNotification.queryNotificationReason
                let recordID = queryNotification.recordID
    
                print("reason \(reason)")
                print("recordID \(recordID)")
                // Do your process here depending on the reason of the change
    
                // Add the notification id to the array of processed notifications to mark them as read
                notificationIDsToMarkRead.append(queryNotification.notificationID!)
            }
        }
    
        operation.fetchNotificationChangesCompletionBlock = { (serverChangeToken: CKServerChangeToken?, operationError: NSError?) -> Void in
            guard operationError == nil else {
                // Handle the error here
                return
            }
    
            // Mark the notifications as read to avoid processing them again
            let markOperation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDsToMarkRead)
            markOperation.markNotificationsReadCompletionBlock = { (notificationIDsMarkedRead: [CKNotificationID]?, operationError: NSError?) -> Void in
                guard operationError == nil else {
                    // Handle the error here
                    return
                }
            }
    
            let operationQueue = NSOperationQueue()
            operationQueue.addOperation(markOperation)
        }
    
        let operationQueue = NSOperationQueue()
        operationQueue.addOperation(operation)
    }
    
    
    }