CloudKit: 根据CKQueryNotification删除本地对象

CloudKit: Delete local objects based on CKQueryNotification

我正在构建一个严重依赖 CloudKit 进行数据同步的应用程序。每次应用程序启动时,它都会使用 CKFetchNotificationChangesOperation 赶上服务器上所做的所有更改。这成功地 returns 修改了所有已创建的对象 and/or,但我现在正处于我还希望我的应用程序根据这些消息删除记录的阶段。

在我的应用程序中,我存储在 CoreData 中的每个对象还带有该对象的在线表示的 recordID。这样我就可以很容易地拿起我需要修改的对象。

删除对象时这似乎很难,因为 CloudKit 只有 returns 这些对象的 recordID,并且没有提供我可以用来知道我在 CoreData 中寻找什么对象的 recordType数据库。

问题

如何在具有多种记录类型的情况下正确处理 CloudKit 'deleted' 通知?

如果 CloudKit 没有给您任何已删除记录类型的指示,处理起来会很麻烦。你不能在不知道实体类型的情况下删除 Core Data 中的对象,所以如果 CloudKit 没有给你任何线索,那么你需要检查每个可能具有 recordId.[=16= 的实体]

删除过程与 Core Data 一样。使用诸如 `recordId = %@" 之类的谓词执行获取请求以查找匹配的对象。如果找到一个,请将其删除。除了您必须对每个潜在实体重复此操作。

一种可能有用的方法是将 recordId 存储在一个新的单独实体中。创建一个名为 CKRecordInfo 的新实体,并将 recordId 保留在那里。具有 CloudKit 信息的每个其他实体都将与该实体具有一对一的关系。使用此设置,您将获取新 CKRecordInfo 实体的实例,并删除与其相关的任何对象。

与此同时——我还没有使用过 CloudKit,它会给你 只是 [=10] 有点令人惊讶=] 没有关于记录类型的信息。如果可能的话,从通知中获取信息是最理想的。

根据您在评论中的说明,我建议您在创建订阅时配置 .recordFields 字典。您可以在此字典中传递有限数量的信息,例如记录类型。当您收到删除通知时,您可以从通知对象中解压recordFields。

您可以在 https://developer.apple.com/documentation/cloudkit/ckquerynotification/1428114-recordfields

的 Apple 文档中找到更多信息

更新

这是我的做法。我使用 objective-C,因此您必须整理 SWIFT 语法。但是步骤是:

创建我要在通知中发送的记录数组

创建订阅

创建一个 notificationInfo 对象

将我想要的键数组添加到 notificationInfo 对象

使用 CKModifySubscriptionsOperation

创建子
NSArray *desiredKeys = @[fieldname1, fieldname1, fieldname1];
CKQuerySubscription *subscription = [[CKQuerySubscription alloc] initWithRecordType:recordName
                                                                          predicate:searchConditions
                                                                     subscriptionID:subscriptionID
                                                                            options:fireOn];

CKNotificationInfo *notificationInfo = [CKNotificationInfo new];
notificationInfo.shouldBadge = shouldBadge;
notificationInfo.desiredKeys = desiredKeys;

subscription.notificationInfo = notificationInfo;

CKModifySubscriptionsOperation *subOp = [[CKModifySubscriptionsOperation alloc] initWithSubscriptionsToSave:subsToCreate subscriptionIDsToDelete:subsToDelete];
subOp.modifySubscriptionsCompletionBlock = ^(NSArray<CKSubscription *> *savedSubscriptions,
                                             NSArray<NSString *> *deletedSubscriptionIDs,
                                             NSError *operationError)
{
   //do whatever
}

subOp.database = database;      //set to either public or private DB
[myQueue addOperation:subOp];

当您收到通知时,只需将对象从 notificationInfo 中拉回即可:

    NSString *value1 = [queryNotification.recordFields objectForKey:fieldname1];

如果它不允许您实际添加 recordType,那么您可能必须创建一个带有记录类型指示符的自定义字段,然后按照我上面的描述传递它,或者通过以下方式获取有问题的记录使用您在通知中收到的记录 ID。