Observe CKRecord deletion via CKSubscription does

2019-02-06 20:11发布

问题:

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)")
        }
    })
}

回答1:

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)")
        }
    })
}