Observe CKRecord deletion via CKSubscription does not work
Asked Answered
I

1

8

CKSubscription doc says: When a record modification causes a subscription to fire, the server sends push notifications to all devices with that subscription except for the one that made the original change to the record.

Let assume I have two devices: device 1 and device 2 logged in from different iCloud accounts. Let assume both devices subscribed for record deletion for a certain record type.

  1. If device 1 creates a record and then device 1 deletes it then device 2 get notified - THAT IS ACCORDING TO THE DOC, BUT ..
  2. If device 1 creates a record and then device 2 deletes it then device 2 get notified - I do NOT think it is ACCORDING TO THE DOC, and IT DOES NOT MAKE ANY SENSE, device 2 deleted it so device 1 should be notified

SET UP SUBSCRIPTION ON DEVICE 1 AND DEVICE 2

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert, categories: nil))
    application.registerForRemoteNotifications()

    let defaultContainer = CKContainer.defaultContainer()
    let publicDatabase = defaultContainer.publicCloudDatabase

    publicDatabase.fetchAllSubscriptionsWithCompletionHandler({subscriptions, error in

        if error == nil {

            if subscriptions.count == 0 {

                let subscription = CKSubscription(recordType: "OU", predicate: NSPredicate(value: true), options: .FiresOnRecordDeletion)
                subscription.notificationInfo = CKNotificationInfo()
                subscription.notificationInfo.shouldBadge = false
                subscription.notificationInfo.alertBody = "OU removed or upated"
                publicDatabase.saveSubscription(subscription, completionHandler: {subscription, error in
                    if error == nil {
                    } else {
                        println("\(error.localizedDescription)")
                    }
                })
            }

        } else {
            println("\(error.localizedDescription)")
        }
    })


    return true
}

CREATE RECORD on DEVICE 1

@IBAction func addOU(sender: AnyObject) {

    var defaultContainer = CKContainer.defaultContainer()
    var publicDatabase = defaultContainer.publicCloudDatabase

    let r = CKRecord(recordType: "OU", recordID: CKRecordID(recordName: "aaaa"))
    publicDatabase.saveRecord(r, completionHandler: { r2, error in

        if error == nil {
        } else {
            println("\(error.localizedDescription)")
        }
    })
}

DELETE RECORD ON DEVICE 2

@IBAction func removeOU(sender: AnyObject) {

    var defaultContainer = CKContainer.defaultContainer()
    var publicDatabase = defaultContainer.publicCloudDatabase

    publicDatabase.deleteRecordWithID(CKRecordID(recordName: "aaaa"), completionHandler: {recordID, error in

        if error == nil {

        } else {
            println("\(error.localizedDescription)")
        }
    })
}
Instauration answered 13/9, 2014 at 9:56 Comment(1)
I've radared the bug rdar://18810914Groceries
I
9

I still think that IT MAKE NO SENSE how CKSubscription works, but as a temporary fix I recommend to changed first CKRecord's lastModifiedUserRecordID to the user who want to delete the record, and only afterwards to delete record.

To change lastModifiedUserRecordID you have to fetch it and without do anything on it save it back, and then deletion can come:

@IBAction func removeOU(sender: AnyObject) {

    var defaultContainer = CKContainer.defaultContainer()
    var publicDatabase = defaultContainer.publicCloudDatabase

    publicDatabase.fetchRecordWithID(CKRecordID(recordName: "aaaa"), completionHandler: {record, error in

        if error == nil {

            publicDatabase.saveRecord(record, completionHandler: {record2, error in

                if error == nil {

                    publicDatabase.deleteRecordWithID(CKRecordID(recordName: "aaaa"), completionHandler: {recordID, error in

                        if error == nil {

                        } else {
                            println("\(error.localizedDescription)")
                        }
                    })
                } else {
                    println("\(error.localizedDescription)")
                }
            })

        } else {
            println("\(error.localizedDescription)")
        }
    })
}
Instauration answered 4/10, 2014 at 13:2 Comment(13)
oh my god... Does this bug was reported? Radar?Groceries
got familiar trouble and your workaround helped me. In my case was following problem: Device 1 created a record and subscribed for the record gets deleted. Device 2 deleted the record. Device 1 not get notified.Groceries
me too rdar://18810914Groceries
I have reported 3 issues regarding CKSubscription :-(Zealotry
this is insane. caused me 3 weeks of troubleshooting my offline-sync feature.Pebbly
i just tried it, doesn't work for private databases.Pebbly
There are public databases and private databases in CloudKit. Private databases are user specific data that other users cannot see.Pebbly
I spent hours just to find out that the subscriptions was broken last days. The workaround had been working for me for some time a month ago, but now it doesn't. @Ninja why do you think the subscriptions must work in private db? Have you ever wanted a push notification that notifys you about the action you just done? I don't think so.Groceries
@Instauration I even tried to add bool attribute to my Record Type and change it's value before re-save the record back. Doesn't helps. Can you say something? Does your solution still works for you?Groceries
@purrrminator there is one use case, for example: to ping other devices to sync new data from a private database.Pebbly
@Ninja I got it, good one. Have you tried zone subscriptions? I think they should work without the workaround, described here. Not sure if they are able to filter out particular record's changes though.Groceries
I've just received an answer to the bugreport, I created according to this question. They said that it is fixed now. Can anyone approve this? Will check this later right on my app.Groceries
I've just checked the bugfix. It is fixed indeed. Hooray!Groceries

© 2022 - 2024 — McMap. All rights reserved.