RestKit + CoreData:操作成功时替换实体内容,失败时保持原样

Posted

技术标签:

【中文标题】RestKit + CoreData:操作成功时替换实体内容,失败时保持原样【英文标题】:RestKit + CoreData: replace entity content in case of operation success, leave as it is in case of failure 【发布时间】:2014-01-23 10:34:55 【问题描述】:

我在如下结构中实现了一个简单的 REST 请求:

RKManagedObjectRequestOperation *operation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
operation.targetObject = nil;
operation.savesToPersistentStore = YES;
operation.managedObjectContext = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
operation.managedObjectCache = [RKManagedObjectStore defaultStore].managedObjectCache;

[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) 
    // Handle success   
 failure:^(RKObjectRequestOperation *operation, NSError *error) 
    // Handle failure
];

如何修改代码,以便:

如果成功,我需要清空 DB 上的相关实体,并将其内容替换为来自 WS 的新实体(不更新,替换整个内容); 如果发生故障,不应发生任何事情,并且 DB 上的实体必须保持原样。

为了删除数据库实体,在操作之前我会按照此处报告的方式进行操作: Core Data: Quickest way to delete all instances of an entity, 但无论 WS 答案是什么,这都会清空实体。

非常感谢任何帮助, 非常感谢, 丹

EDIT1:

按照@Wain 的建议,我在操作中添加了一个获取请求块,如下所示:

RKFetchRequestBlock fetchRequestBlock = ^NSFetchRequest *(NSURL *URL)

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"EntityToBeUpdated"];
    fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:NO] ];
    return fetchRequest;
;

operation.fetchRequestBlocks = @[fetchRequestBlock];
operation.deletesOrphanedObjects = YES;

但结果没有改变:db 上的项目没有更新或删除。

【问题讨论】:

【参考方案1】:

RestKit 是基于更新而不是替换。因此,您的要求在映射期间很难管理。你可以考虑:

    让 RestKit 创建一个新实例并在成功块中删除旧实例 - 短时间内重复对象。 使用动态映射来检查响应,然后再开始映射以决定是否删除 - 有点 hacky。 让 JSON 响应包含所有键的值,这样所有内容都会被覆盖。

从错误的角度来看,如果错误返回一个 HTTP 状态代码,并且您没有该代码的响应描述符,那么 RestKit 将不会改变任何内容。


根据您在下面的评论,您实际上是在寻找孤立项目删除。这是使用获取请求块完成的。请参阅Fetch Request Blocks and Deleting Orphaned Objects here 部分。您不需要谓词,只需一个获取请求。

【讨论】:

嗨 Wain,WS 的回答如下:“items”:[“id”:“1”,“type”:“type1”,“label”:“label1”, "order": "1" , "id" : "2", "type": "type2", "label": "label2", "order": "2" ] 可以更改为:"items ": [ "id" : "1", "type": "type5", "label": "label5", "order": "1" ] 这意味着必须用新的值更新第一项,并且第二个删了。是否有可能或者我必须如上所述清空实体? 感谢您对使用获取请求块的建议。为了使用它,我应该保留上面写的所有代码,只需添加 operation.fetchRequestBlocks = ... ? 我会使用对象管理器而不是操作,它更容易并且提供更多功能。 由于我不清楚如何按照建议使用对象管理器来实现这一点,因此我尝试添加一个 fetchRequestBlocks,请参阅上面代码中的 EDIT1,但没有任何改变.. 我假设实体名称是正确的。你真的不需要排序描述符。您是否添加了日志/断点来检查它是否被使用?您是否在之前、之后和更新时记录上下文内容?所有这些日志都显示了什么?

以上是关于RestKit + CoreData:操作成功时替换实体内容,失败时保持原样的主要内容,如果未能解决你的问题,请参考以下文章

RestKit w/ CoreData 拯救 MOC 混乱

Restkit + Coredata - NSFetchedResultsControllerDelegate 回调不会单独为更新操作触发

RestKit .20 with CoreData - 如何设置默认值

使用 RestKit 0.2 从 CoreData 获取本地数据

RestKit 对象映射 POST 响应,“CoreData:错误:在 NSManagedObject 类映射操作上调用指定初始化程序失败”

RestKit:无法使用 coredata 执行映射