2014-09-12 12 views
8

我想上傳與CloudKit一些記錄更改。我正在使用CKModifyRecordsOperation來批量上傳設備上已更改的記錄。這些記錄都在一個自定義區域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"> 
}> 

回答

5

正好是在你的self.localChanges陣列是什麼? CKRecord我假設,但是您上傳的修改記錄是基於您從CloudKit下載的相同CKRecord對象嗎?

我也有類似的(雖然不是精確的)錯誤消息當我試圖上傳我的地方變化的新分配CKRecord和預期它來覆蓋服務器的副本。我通過下載我的項目的遠程副本,將更新應用到由CloudKit給我的CKRecord實例,然後上載它來修復它。

+0

是的,他們是CKRecords,是的,我用新鮮的CKRecords覆蓋現有的,並且你的解決方案工作!在文檔中不是非常明確。好吧。感謝你的回答! – Jonathan 2014-10-09 04:51:40

2

你應該在dashboa的相應記錄類型組寫權限 rd,我想。

enter image description here

+0

沒想到要這樣做。只是給它一個鏡頭,它沒有奏效。 – Jonathan 2014-09-24 22:46:33

0

值得注意的是,解決這個是雙重的。我也在嘗試使用自定義區域。無論我是初始化CKRecordZoneID的代碼是這樣的:

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

這應該是這個樣子的

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

我認爲,這是什麼導致了「保護數據不匹配的部分Bug「,但Dave Teare的回答也是必要的補救措施。

7

如果使用savePolicyCKRecordSaveIfServerRecordUnchanged,則需要在CKModifyRecordsOperation之前預取遠程CKRecord(並更新該特定實例)。如果您分配一個「本地」 CKRecord和向上的參考與匹配initWithRecordName:它通過CKRecordID,CloudKit不能遠程改變標籤比較的(缺失)局部改變標籤,所以它失敗CKErrorServerRecordChanged和有些模糊的錯誤信息: 「保護數據不匹配」。

但是,如果遠程CKRecord完全不存在,肯定是服務器記錄沒有改變,保存操作可以繼續進行。此行爲是「保存如果不存在」用例(SQL:基於PRIMARY KEY的INSERT)的基礎。如果您分配「本地」CKRecord並使用savePolicyCKRecordSaveIfServerRecordUnchanged,它將INSERT,但從不更新。

如果您使用的CKRecordSaveAllKeyssavePolicyCKOwnerDefaultNameCKRecordZoneIDownerName,你應該能夠節省:通過「本地」(SQL UPDATE,用INSERT如有必要)分配CKRecord,節約了(預取)之旅通過網絡。

「保存是否存在」用例(SQL:UPDATE在PRIMARY KEY)可能不能沒有通過網絡(覈查)的行程來完成。

一個問題:這是不可能滾動兩者CKRecordSaveIfServerRecordUnchanged INSERT和CKRecordSaveAllKeys UPDATE到一個原子事務中,由於CloudKit交易僅單個CKModifyRecordsOperation跨越,跨多個CKRecord/CKRecordID實例。從哲學上講,「事務」應該能夠跨越多個「操作」(SQL:查詢),而不僅僅是多個「記錄」(SQL:行)。