当我使用CKModifyRecordsOperation将多个表的记录保存到私有云数据库的默认区域时,除了表‘X’之外,它总是在下面返回错误:
将记录保存到服务器的错误:从“X”类型更新记录到“Y”的尝试无效
error.userInfo的详细信息:
{ 1:(_defaultZone:defaultOwner) =“CKErrorDescription =”错误保存记录CKRecordID: 0x7fd7a3d4c0c0;CKErrorDescription到服务器:从“X”类型更新记录到“Y”的尝试无效; ContainerID =“iCloud.com.”; NSDebugDescription = "CKInternalErrorDomain: 2006"; NSLocalizedDescription =“将记录保存到服务器:将记录从”X“类型更新到”Y“的无效尝试; NSUnderlyingError = "CKError 0x7fa0d250c4e0:\“(2006年);服务器消息=\\”试图从'X‘类型更新记录到’Y‘\’的无效尝试;uuid = E2E...D1E;容器ID =\“iCloud.com.\”; RequestUUID = "E2E...D1E"; ServerErrorDescription =“将记录从”X“类型更新为”Y“的无效尝试”; errorKey = ck1rosofi; }
相关代码片段:
- (void)sync
{
...
NSMutableArray * operations;
for (NSString *tableName in @[@"X", @"Y"]) {
CKModifyRecordsOperation * operation = [self _modifyRecordsOperationWithTableName:tableName];
if (operation) {
if (operations) [operations addObject:operation];
else operations = [NSMutableArray arrayWithObject:operation];
}
}
if (operations) {
[operationQueue addOperations:operations waitUntilFinished:NO];
}
}
- (CKModifyRecordsOperation *)_modifyRecordsOperationWithTableName:(NSString *)tableName
{
...
NSMutableArray * recordsToSave = [NSMutableArray array];
for (KYModel <KYModel_iCloudProtocol> *instance in unsyncedInstances) {
CKRecordID * objectID = [[CKRecordID alloc] initWithRecordName:@(instance.id).stringValue];
CKRecord * cloudRecord = [[CKRecord alloc] initWithRecordType:tableName recordID:objectID];
... setup record detail
[recordsToSave addObject:record];
}
CKModifyRecordsOperation * operation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave recordIDsToDelete:nil];
operation.database = [[CKContainer defaultContainer] privateCloudDatabase];
operation.savePolicy = CKRecordSaveAllKeys;
operation.qualityOfService = NSQualityOfServiceUserInteractive;
operation.atomic = NO;
operation.perRecordProgressBlock = ...;
operation.perRecordCompletionBlock = ^(CKRecord *record, NSError *error) {
if (error) {
// got error here
}
...
};
operation.modifyRecordsCompletionBlock = ...;
return operation;
}发布于 2016-05-17 13:44:22
在搜索和调试了一段时间之后,我意识到那些失败的记录具有相同的“记录名”(它是CKRecordID的唯一名称,它类似于每个记录的唯一ID ),尽管它们属于不同的表。
解决方案一:
使CKRecordID的“记录名”在所有表中都是唯一的。
例如,为每个记录名添加一个表名前缀: table_name_id。
上面我的例子的问题是相同区域(默认区域)中不同表的记录重复的“记录名称”。
使用CKModifyRecordsOperation的CKRecordSaveAllKeys保存策略,当对表Y保存记录(id:1)时,它在云端查找表X的另一个记录(id:1),并尝试修改它,从而引发错误“将记录从'X‘类型更新到’Y‘类型的无效尝试。
解决方案二:
为每个表创建自定义区域(注意:自定义区域仅适用于私有云数据库)。
例如,与其使用默认区域,不如对表X使用自定义区域"X_Zone“,对表Y使用"Y_Zone”,然后我们可以继续使用@"id“作为CKRecordID的”记录名“。
通过这种方式,在将本地记录转换为CKRecord实例时,还需要提供CKRecord:
CKRecordZoneID *zoneID = [[CKRecordZoneID alloc] initWithZoneName:@"Custom_Zone_Name_Here"
ownerName:CKOwnerDefaultName];
CKRecordID *objectID = [[CKRecordID alloc] initWithRecordName:@(instance.id).stringValue zoneID:zoneID];
...当然,您需要首先创建相关的自定义区域:
CKRecordZone *zone = [[CKRecordZone alloc] initWithZoneName:@"Custom_Zone_Name"];
[[[CKContainer defaultContainer] privateCloudDatabase] saveRecordZone:zone completionHandler:...];或者同时创建多个:
NSMutableArray *zones = [NSMutableArray array];
for (NSString *zoneName in @[...]) {
CKRecordZone *zone = [[CKRecordZone alloc] initWithZoneName:zoneName];
[zones addObject:zone];
}
CKModifyRecordZonesOperation * operation = [[CKModifyRecordZonesOperation alloc] initWithRecordZonesToSave:zones recordZoneIDsToDelete:nil];
...
[[[CKContainer defaultContainer] privateCloudDatabase] addOperation:operation];我已经测试了这两种方法&正如预期的那样工作。
建议:
如果您的记录存储在私有云数据库中,我认为解决方案二将是一个不错的选择,正如DOC所说:
..。使用自定义区域在私有数据库中安排和封装相关记录组。自定义区域也支持其他功能,例如将多个记录写入单个原子事务的能力。将每个自定义区域视为与数据库中的每个其他区域分离的单个数据单元。在区域内,您可以添加记录,就像添加其他任何地方一样。..。
处理每个表的记录要方便得多,比如删除表的区域,而不是查询和删除同一区域中表的记录。
但请注意,如果您在表中使用CKReference,那么请不要对这些表使用自定义区域。
..。CKReference类不支持跨区域链接,因此每个引用对象必须指向与当前记录相同的区域中的记录。
顺便说一句,这是自己回答的问题的答案,希望别人得到同样的问题会有所帮助。如果我的回答有什么问题,请指出,并欢迎任何建议,提前。:)
https://stackoverflow.com/questions/37277962
复制相似问题