RestKit 发布嵌套的托管对象会创建重复项
Posted
技术标签:
【中文标题】RestKit 发布嵌套的托管对象会创建重复项【英文标题】:RestKit POSTing Nested Managed Objects Creates Duplicates 【发布时间】:2014-04-11 17:04:30 【问题描述】:我在使用 RestKit 发布带有嵌套 NSManagedObjects 的 NSManagedObject 时遇到了一些困难。当 POST 返回时,我似乎得到了插入 CoreData 的子 NSManagedObjects 的重复记录。这是模型的快照:
这是我发布的 JSON:
"actions": [],
"application": "Identify",
"createBy": "welcomed",
"createDt": "2014-04-11T16:26:15Z",
"description": null,
"externalId": null,
"groupId": "5",
"id": 0,
"images": [
"format": "JPEG",
"height": 200,
"id": 0,
"image": "/9j/4A..../Pv5n/9k=",
"status": "C",
"type": "MUGSHOT",
"width": 200
],
"locked": null,
"modifyBy": null,
"modifyDt": null,
"priv": null
这是 POST 后从服务返回的 JSON:
"actions": [],
"application": "Identify",
"createBy": "welcomed",
"createDt": 1397233575000,
"description": null,
"externalId": null,
"groupId": "5",
"id": 11,
"images": [
"captureDevice": null,
"createBy": null,
"createDt": null,
"format": "JPEG",
"height": 200,
"id": 11,
"image": "/9j/4AAQSkZJR.../Pv5n/9k=",
"recordId": 11,
"status": "C",
"type": "MUGSHOT",
"width": 200
],
"locked": false,
"modifyBy": null,
"modifyDt": null,
"priv": false
编辑(我想这很重要):这是 WTSImage 和 WTSRecord 的映射:
RKEntityMapping *recordMapping = [RKEntityMapping mappingForEntityForName:@"WTSRecord" inManagedObjectStore:self.managedObjectStore];
[recordMapping addAttributeMappingsFromDictionary:@
@"id":@"dbId",
@"externalId":@"extId",
@"groupId":@"groupId",
@"application": @"application",
@"description": @"desc",
@"priv": @"priv",
@"locked": @"locked",
@"createBy": @"createBy",
@"createDt": @"createDt",
@"modifyBy": @"modifyBy",
@"modifyDt": @"modifyDt",
];
recordMapping.identificationAttributes = @[@"dbId"];
//image mapping
RKEntityMapping *imageMapping = [RKEntityMapping mappingForEntityForName:@"WTSImage" inManagedObjectStore:self.managedObjectStore];
[imageMapping addAttributeMappingsFromDictionary:@
@"id": @"dbId",
@"status": @"status",
@"type": @"type",
@"format": @"format",
@"width": @"width",
@"height": @"height",
@"image": @"base64Image"
];
imageMapping.identificationAttributes = @[@"dbId"];
[recordMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"images" toKeyPath:@"images" withMapping:imageMapping]];
以下代码是我创建 NSManagedObjects 并调用 [RKObjectManager postObject:path:parameters:success:failure:
的地方:
WTSRecord *record = [NSEntityDescription insertNewObjectForEntityForName:@"WTSRecord" inManagedObjectContext:self.managedObjectContext];
record.createBy = @"welcomed";
record.createDt = [NSDate date];
record.application = kWTSApplicationIdentify;
record.groupId = @"5";
WTSImage *image = [NSEntityDescription insertNewObjectForEntityForName:@"WTSImage" inManagedObjectContext:self.managedObjectContext];
image.height = [NSNumber numberWithFloat:mugshot.size.height];
image.width = [NSNumber numberWithFloat:mugshot.size.width];
image.imageData = UIImageJPEGRepresentation(imageData, 1.0);
image.type = kWTSCaptureTypeMugshot;
image.format = kWTSCaptureFormatJpeg;
image.status = kWTSCaptureStatusCaptured;
image.record = record;
[record addImagesObject:image];
RKObjectManager *manager = [RKObjectManager sharedManager];
[manager postObject:record path:@"records" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
failure:^(RKObjectRequestOperation *operation, NSError *error)
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error Sending Record" message:error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
];
当调用成功块时,我检查 sqlite 数据库并插入了 1 个 WTSRecord 和 2 WTSImages。其中一个 WTSImage 具有 WTSRecord 的正确 FK 和数据库中的 PK,而另一个似乎是孤立的(未设置 dbId 和 WTSRecord 的 FK)。
这里是 RestKit 和 Core Data 跟踪日志的链接:https://dl.dropboxusercontent.com/u/466390/restkit2.txt
希望有人可以提供帮助!谢谢!
EDIT经过一番搜索,我找到了这个页面:https://github.com/RestKit/RestKit/issues/1228
在将 UUID 发布到 REST 服务之前,我是否必须在客户端使用 UUID 创建标识元素?如果不先在客户端设置标识属性,RestKit 是否无法将请求对象映射回对象存储中已创建的对象?
【问题讨论】:
【参考方案1】:对于发布的对象,RestKit 了解如何使用响应数据更新该项目,但这不适用于关系内容。从技术上讲,它可以被编码,但目前还不是。
如果您需要映射后关系中的对象与您创建的对象相同,那么您就有问题了。如果您不介意它是一个不同的对象,那么问题只是删除重复项......
重复删除:
在处理 POST 响应时不使用获取请求块,因此您需要获取副本并手动将其删除。我将假设任何与记录具有 nil 关系的图像都是骗子,因此执行起来相对简单。
【讨论】:
我使用过的大多数允许创建图像容器的 API 都需要先创建容器,然后再进行多次上传(每个图像一个)。从网络管理的角度来看,这通常会更好,并且可以解决您的问题,因为每个发布的对象都会按照您的预期进行更新。 感谢 Wain 提供的信息!老实说,您是 RestKit 之神,过去几天您的回答为我节省了很多时间!与使用客户端生成的 UUID(我发现它能够更新嵌套的托管对象)相比,我更喜欢您的解决方案。我宁愿不处理数据库中额外的唯一标识符,所以我认为清理任何具有 nil 关系的图像是要走的路。感谢您确认 RestKit 的限制,以便我可以继续实际做一些工作。 :) 嗨@Wain,现在还是这样吗?我需要发送一堆已经存在于数据库中的相关对象,如果它们被映射,我希望它们与主对象相同,从而避免重复。非常感谢!以上是关于RestKit 发布嵌套的托管对象会创建重复项的主要内容,如果未能解决你的问题,请参考以下文章
当响应包含在数组中时,RestKit POSTed 托管对象变得重复
如何使用 RestKit 将嵌套的 JSON 对象存储到核心数据中