CloudKit:基于CKQueryNotification删除本地对象

时间:2017-07-31 15:25:50

标签: ios swift core-data icloud cloudkit

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

在我的应用程序中,我存储在CoreData中的每个对象也携带该对象的在线表示的recordID。这样我就可以轻松找到需要修改的对象。

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

问题

如何正确处理CloudKit'已删除'有多种记录类型的情况下的通知?

2 个答案:

答案 0 :(得分:4)

如果CloudKit没有给出任何已删除记录类型的指示,那么处理起来就很麻烦。在不知道实体类型的情况下,您无法删除Core Data中的对象,因此如果CloudKit没有为您提供任何线索,那么您需要检查每个可能具有recordId的实体。

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

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

与此同时 - 我还没有使用过CloudKit,而且它会给你只是 recordId并且没有关于记录类型的信息,这有点令人惊讶。如果可能的话,从通知中获取信息将是理想的。

答案 1 :(得分:3)

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

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

的Apple文档中找到更多信息

<强>更新

以下是我的表现方式。我使用objective-C,因此您必须整理SWIFT语法。但步骤是:

创建我想在notif中发送的记录数组

创建订阅

创建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,那么您可能必须创建一个带有记录类型指示符的自定义字段,然后按照上面的描述传递,或者通过以下方式获取相关记录使用您在通知中收到的recordID。