8

我正在尝试使用 CloudKit 上传一些记录更改。我正在尝试使用 CKModifyRecordsOperation 批量上传设备上已更改的记录。记录都在自定义区域中

出于某种原因,该操作不断返回错误消息,告诉我“保护数据不匹配”

这是代码:

- (void)updloadLocalChangesWithCompletionBlock:(void (^)(NSError *error))completionBlock
{
   // Initialize the data
   NSArray *localChanges = self.localChanges;
   NSArray *localDeletions = self.localDeletions;

   // Initialize the database and modify records operation
   CKDatabase *database = [CKContainer defaultContainer].privateCloudDatabase;
   CKModifyRecordsOperation *modifyRecordsOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:localChanges recordIDsToDelete:localDeletions];
   modifyRecordsOperation.savePolicy = CKRecordSaveAllKeys;

   NSLog(@"CLOUDKIT Changes Uploading: %d", localChanges.count);

   // Add the completion block
   modifyRecordsOperation.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *error) {
       if (error) {
           NSLog(@"[%@] Error pushing local data: %@", self.class, error);
       }

       [self.localChanges removeObjectsInArray:savedRecords];
       [self.localDeletions removeObjectsInArray:deletedRecordIDs];

       completionBlock(error);
   };

   // Start the operation
   [database addOperation:modifyRecordsOperation];
}

这是它给我的错误:

[CloudKitSyncManager] Error Uploading Changes: <CKError 0x156654a0: "Partial Failure" (2/1011); "Failed to modify some records"; partial errors: {
    default-00001:(ZoneName:UserRecordID) = <CKError 0x1550b5a0: "Server Record Changed" (14/2037); "Error saving record <CKRecordID: 0x18080430; default-00001:(ZoneName:UserRecordID)> to server: Protection data didn't match">
}>
4

4 回答 4

7

如果您使用savePolicyof CKRecordSaveIfServerRecordUnchanged,则必须在 之前预取远程CKRecord(并更新该特定实例)CKModifyRecordsOperation。如果您分配一个“本地”并通过匹配CKRecord向上引用它,CloudKit 无法将远程更改标签与(丢失的)本地更改标签进行比较,因此它会失败并出现一些模糊的错误消息:“保护数据没有不匹配”。CKRecordIDinitWithRecordName:CKErrorServerRecordChanged

但是,如果远程CKRecord根本不存在,那么服务器记录肯定没有改变,保存操作可以继续进行。此行为是“如果不存在则保存”用例(SQL:INSERT over a PRIMARY KEY)的基础。如果您分配一个“本地”CKRecord并使用savePolicyof CKRecordSaveIfServerRecordUnchanged,它将插入,但从不更新。

如果您使用savePolicyofCKRecordSaveAllKeysCKRecordZoneID ownerNameof CKOwnerDefaultName,您应该能够通过“本地”分配来保存(SQL:UPDATE,必要时使用 INSERT)CKRecord,从而节省网络上的(预取)行程。

“如果存在则保存”用例(SQL:通过主键更新)可能无法通过网络进行(验证)旅行。

一个问题:不可能同时将CKRecordSaveIfServerRecordUnchangedINSERT 和CKRecordSaveAllKeysUPDATE 滚动到一个原子事务中,因为 CloudKit 事务只跨越一个CKModifyRecordsOperation,跨越多个CKRecord/CKRecordID实例。从哲学上讲,一个“事务”应该能够跨越多个“操作”(SQL:查询),而不仅仅是多个“记录”(SQL:行)。

于 2015-08-07T06:13:36.523 回答
6

您的self.localChanges阵列中到底有什么?CKRecord我假设,但是您上传的修改记录是否基于您从 CloudKit 下载的相同 CKRecord 对象?

当我尝试使用本地更改上传新分配的 CKRecord 并希望它覆盖服务器的副本时,我收到了类似的(尽管不准确)错误消息。我通过下载我的项目的远程副本、将更新应用到 CloudKit 提供给我的 CKRecord 实例,然后上传它来修复它。

于 2014-10-04T00:45:07.330 回答
2

我猜你应该在仪表板中为相应的记录类型设置写权限。

在此处输入图像描述

于 2014-09-17T07:25:31.177 回答
0

值得注意的是,对此的解决方案有两个。我还尝试使用自定义区域。无论我在哪里初始化 CKRecordZoneID,代码看起来都是这样的:

[[CKRecordZoneID alloc] initWithZoneName:@"CustomZoneName" ownerName:self.userRecordId.recordName];

这应该看起来像这样

 [[CKRecordZoneID alloc] initWithZoneName:@"CustomZoneName" ownerName:CKOwnerDefaultName];

我相信这是导致“保护数据不匹配错误”的部分原因,但 Dave Teare 的回答也有必要对其进行补救。

于 2014-10-09T04:59:01.090 回答