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)")
        }
    })
}
János
  • 32,867
  • 38
  • 193
  • 353

1 Answers1

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)")
        }
    })
}
János
  • 32,867
  • 38
  • 193
  • 353
  • oh my god... Does this bug was reported? Radar? – kas-kad Oct 29 '14 at 14:58
  • 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. – kas-kad Oct 29 '14 at 15:14
  • 1
    me too rdar://18810914 – kas-kad Oct 29 '14 at 16:59
  • 2
    I have reported 3 issues regarding `CKSubscription` :-( – János Oct 29 '14 at 18:01
  • this is insane. caused me 3 weeks of troubleshooting my offline-sync feature. – ninjaneer Dec 06 '14 at 11:48
  • i just tried it, doesn't work for private databases. – ninjaneer Dec 06 '14 at 12:03
  • There are public databases and private databases in `CloudKit`. Private databases are user specific data that other users cannot see. – ninjaneer Dec 06 '14 at 12:09
  • 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. – kas-kad Dec 11 '14 at 16:38
  • @János 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? – kas-kad Dec 11 '14 at 16:46
  • @purrrminator there is one use case, for example: to ping other devices to sync new data from a private database. – ninjaneer Dec 11 '14 at 20:36
  • @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. – kas-kad Dec 12 '14 at 13:08
  • 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. – kas-kad Mar 28 '15 at 07:22
  • I've just checked the bugfix. It is fixed indeed. Hooray! – kas-kad Mar 28 '15 at 20:16