RestKit / CoreData:两次请求相同的URL时插入重复的对象而不是合并
Posted
技术标签:
【中文标题】RestKit / CoreData:两次请求相同的URL时插入重复的对象而不是合并【英文标题】:RestKit / CoreData: Duplicate objects inserted instead of merged when requesting the same URL twice 【发布时间】:2014-04-09 19:06:13 【问题描述】:我的应用程序使用 RestKit 从 URL 获取,其有效负载包含 JSON 格式的对象(医院)列表。我第一次点击 URL 时,一切正常 - 有效负载被正确转换为一组 Hospital
托管对象,并将它们插入到持久存储中(通过执行获取请求并将结果与有效负载进行比较来验证)。
如果我从同一个 URL 再次执行 GET,返回相同的有效负载,RestKit 会将另一组 Hospital
对象(与第一组相同)插入到持久存储中。我希望 RestKit 确定第二组 Hospital
对象与第一组相同,然后在必要时更新第一组对象。
有效负载包含一个名为provider_number
的唯一标识符。
我在Hospital
模型中添加了一个provider_number
字段并勾选了Indexed
。
我相应地在RKEntityMapping
上设置了标识属性:
+ (RKEntityMapping *) hospitalMapping
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Hospital" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
[mapping setIdentificationAttributes:@[ @"provider_number"]];
[mapping addAttributeMappingsFromDictionary:[self hospitalAttributeDictionary]];
return mapping;
根据http://restkit.org/api/latest/Classes/RKManagedObjectRequestOperation.html#overview,我使用持久 MOC 在RKManagedObjectStore
上创建了托管对象缓存:
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
RKObjectManager
配置为使用持久 MOC:
RKManagedObjectStore *managedObjectStore = [RKManagedObjectStore defaultStore];
NSManagedObjectContext *managedObjectContext = [managedObjectStore persistentStoreManagedObjectContext];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:url];
objectManager.managedObjectStore = managedObjectStore;
RKObjectManager
进一步配置了响应描述符和请求的响应 MIME 类型。
然后将映射操作排入队列:
[objectManager getObjectsAtPath:@""
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
NSError *executeError = nil;
if([managedObjectContext saveToPersistentStore:&executeError])
NSLog(@"Saved hospitals to persistent store.");
else
NSLog(@"Failed to save to data store");
failure:^(RKObjectRequestOperation *operation, NSError *error)
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
];
执行两次会导致持久存储中的重复对象。我错过了什么?
【问题讨论】:
您是否看到数据存储中设置的provider_number
(当您记录新的托管对象实例时)?
附注您无需在成功块中调用saveToPersistentStore:
- 到那时它已经保存...
嗨@Wain,感谢您的回复。是的,provider_number
已正确映射:RKMapperOperation.m:403 Finished performing object mapping. Results: "" = ( "<Hospital: 0xa537e10> (entity: Hospital; id: 0xa52b500 <x-coredata:///Hospital/t296C047A-2D63-4AF4-9DDF-F5C422D3A10B15> ; data: \n \"provider_number\" = 450056;\n)", );
感谢您的提示,我将删除对 saveToPersistentStore
的无关调用。
您是否对同一实体有另一个映射,但 identificationAttributes
设置为不同的值?
【参考方案1】:
来自此日志:
restkit.core_data:RKFetchRequestManagedObjectCache.m:124 找到对象'( )' using fetchRequest' (entity: Hospital; predicate: (provider_number == nil); sortDescriptors: ((null)); type: NSManagedObjectResultType; )'
Restkit 正在寻找现有项目,但谓词错误:predicate: (provider_number == nil)
目前还不清楚为什么。在managedObjectsWithEntity:attributeValues:inManagedObjectContext:
开头的RKFetchRequestManagedObjectCache.m
中放置一个断点,并检查备份堆栈以了解创建attributeValues
的内容以及provider_number
未正确完成的原因。
【讨论】:
确实如此。我想知道为什么它是零?我的猜测是 RK 正在构建涉及provider_number
的谓词,因为我添加了 provider_number
作为实体标识属性,但如果我理解正确,看起来 RK 并没有用 @ 的值填充比较的另一边987654328@ 为 RK 刚刚创建的对象。我将设置断点并深入研究它...
想通了。 RKTransformedValueWithClass() 返回 nil,因为它无法将实体的标识属性解析为类型(它是可转换的)。我将属性的类型更改为 NSString *,现在识别工作正常。谢谢!以上是关于RestKit / CoreData:两次请求相同的URL时插入重复的对象而不是合并的主要内容,如果未能解决你的问题,请参考以下文章
RestKit + CoreData,理解 RKManagedObjectRequestOperation
如何将 PUT 请求添加到 RestKit + Core Data?
CoreData+RESTKit:来自 NSFetchedResultsController 的同一对象的多个副本