Обратите внимание, что удаление CKRecord через CKSubscription не работает.

CKSubscription doc говорит: Когда модификация записи приводит к срабатыванию подписки, сервер отправляет push-уведомления на все устройства с этой подпиской, кроме того, которое внесло первоначальное изменение в запись. эм>

Предположим, у меня есть два устройства: device 1 и device 2, которые вошли в систему с разных учетных записей iCloud. Предположим, что оба устройства подписались на удаление записи определенного типа.

  1. Если device 1 создает запись, а затем device 1 удаляет ее, то device 2 получает уведомление - ЭТО СОГЛАСНО ДОКУМЕНТУ, НО..
  2. Если device 1 создает запись, а затем device 2 удаляет ее, то device 2 получает уведомление - я НЕ думаю, что это СОГЛАСНО ДОКУМЕНТУ, и ЭТО НЕ ИМЕЕТ НИКАКОГО СМЫСЛА, device 2 удалил его, поэтому device 1 должен быть уведомлен

НАСТРОЙТЕ ПОДПИСКУ НА УСТРОЙСТВЕ 1 И УСТРОЙСТВЕ 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
}

СОЗДАТЬ ЗАПИСЬ на УСТРОЙСТВЕ 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)")
        }
    })
}

УДАЛИТЬ ЗАПИСЬ НА УСТРОЙСТВЕ 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)")
        }
    })
}

person János    schedule 13.09.2014    source источник
comment
Я обнаружил ошибку rdar://18810914.   -  person kas-kad    schedule 29.10.2014


Ответы (1)


Я по-прежнему думаю, что ЭТО НЕ ИМЕЕТ СМЫСЛА, как работает CKSubscription, но в качестве временного исправления я рекомендую сначала изменить CKRecord на lastModifiedUserRecordID пользователю, который хочет удалить запись, и только после этого удалять запись.

Чтобы изменить lastModifiedUserRecordID, вы должны вытащить его и ничего не делать с ним, сохранить его обратно, после чего может произойти удаление:

@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)")
        }
    })
}
person János    schedule 04.10.2014
comment
Боже мой... Сообщалось ли об этой ошибке? Радар? - person kas-kad; 29.10.2014
comment
получил знакомую проблему, и ваш обходной путь помог мне. В моем случае была следующая проблема: Устройство 1 создало запись и подписалось на удаление записи. Устройство 2 удалило запись. Устройство 1 не получает уведомления. - person kas-kad; 29.10.2014
comment
я тоже рдар://18810914 - person kas-kad; 29.10.2014
comment
Я сообщил о 3 проблемах, связанных с CKSubscription :-( - person János; 29.10.2014
comment
это безумие. заставило меня 3 недели устранять неполадки с моей функцией автономной синхронизации. - person ninjaneer; 06.12.2014
comment
я только что попробовал, не работает для частных баз данных. - person ninjaneer; 06.12.2014
comment
В CloudKit есть общедоступные базы данных и частные базы данных. Частные базы данных — это пользовательские данные, которые другие пользователи не могут видеть. - person ninjaneer; 06.12.2014
comment
Я потратил часы, чтобы узнать, что подписки были нарушены в последние дни. Обходной путь работал у меня некоторое время назад месяц назад, но теперь это не так. @Ninja, почему вы думаете, что подписки должны работать в приватной базе данных? Вы когда-нибудь хотели получить push-уведомление, которое уведомляет вас о действии, которое вы только что сделали? Я так не думаю. - person kas-kad; 11.12.2014
comment
@János Я даже пытался добавить атрибут bool к моему типу записи и изменить его значение, прежде чем повторно сохранить запись обратно. Не помогает. Вы можете сказать что-то? Ваше решение все еще работает для вас? - person kas-kad; 11.12.2014
comment
@purrrminator есть один вариант использования, например: пропинговать другие устройства для синхронизации новых данных из частной базы данных. - person ninjaneer; 11.12.2014
comment
@Ninja Я понял, хорошо. Вы пробовали зональные подписки? Я думаю, что они должны работать без обходного пути, описанного здесь. Однако не уверен, что они могут отфильтровать изменения конкретной записи. - person kas-kad; 12.12.2014
comment
Я только что получил ответ на отчет об ошибке, который я создал в соответствии с этим вопросом. Сказали, что сейчас исправят. Кто-нибудь может это одобрить? Проверю это позже прямо в моем приложении. - person kas-kad; 28.03.2015
comment
Я только что проверил исправление. Это действительно исправлено. Ура! - person kas-kad; 28.03.2015