RESTKit:在覆盖之前将 GET 对象与本地持久化的对象进行比较

Posted

技术标签:

【中文标题】RESTKit:在覆盖之前将 GET 对象与本地持久化的对象进行比较【英文标题】:RESTKit: Comparing GET object with locally persisted before overwriting 【发布时间】:2014-04-29 04:02:41 【问题描述】:

我在 Core Data 中有一个保存的对象(持久化)。让我们说下面是值:

//Entity: employee
objectID: 1111
firstName: @"Jon"
lastName: @"D"
modified: @"10:45PM"

现在,我发出RKManagedObjectRequestOperation *operation 请求。

我设置operation.savesToPersistentStore = NO; 并开始操作。

对象已下载并已修改为以下内容:

//Entity: employee
objectID: 1111
firstName: @"Jonathan"
lastName: @"Doe"
modified: @"10:55PM"
//I have 15 other properties that are either Strings, NSDate, NSNumber, and BOOLs

我相信此时修改后的对象在managedObjectContext

如果Context 中的modified 日期不同,我想将Context 中的每个attribute 与Core Data 中保留的日期进行比较。如果Context attribute 与持久化的不同,我需要为每个属性触发一个标志。一旦所有属性都被破解,我可以通过保存上下文来覆盖对象。

我想我必须手动检查:

if (!([objectInCoreData valueForKey:@"firstName"] isEqualToString:[objectInContext valueForKey@"firstName"])) 
 
     firstNameValueChange = YES; // Trigger this flag
     // I have to trigger a flag for each attribute that's changed to show 
     // the changed value in the tableView in a different color


//Continue to check for each attribute, and at end overwrite persisted with Context by
[self.managedObjectContext save:&error];

问题 1:我觉得有更好的方法来做到这一点。最佳做法是什么? 如何简化检查 15 个不同属性的代码?

问题 2:我在哪里测试每个属性是否已更改?在successBlock里面?将保存:方法?

** 更新 *

RKManagedObjectRequestOperation *operation = [[RKManagedObjectRequestOperation alloc]initWithRequest:request responseDescriptors:@[responseDescriptor]];
operation.managedObjectContext = self.objectManager.managedObjectStore.mainQueueManagedObjectContext;
operation.managedObjectCache = appDelegate.managedObjectStore.managedObjectCache;
operation.savesToPersistentStore = NO;


[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 

    NSSet *updatedObjects = [self.managedObjectContext updatedObjects];
    NSLog(@"updatedObjects Count %i", updatedObjects.count);

    NSArray *_updatedObjects = updatedObjects.allObjects;
    NSLog(@"_updatedObjects Count %i", _updatedObjects.count);

    for (int i = 0; i<_updatedObjects.count; i++)
    
        Invite *invite = [_updatedObjects objectAtIndex:i];
        NSDictionary *changedValues = [invite changedValues];            
    
failure:^(RKObjectRequestOperation *operation, NSError *error) 

日志

 I restkit.network:RKObjectRequestOperation.m:250 GET 'http://www.domain.com/api?lastrequest=2014-04-22T07%3A06%3A34Z' (200 OK / 28 objects) [request=0.1140s mapping=0.0865s total=0.3034s]
2014-04-29 07:06:43.112 App[10627:60b] updatedObjects Count 0
2014-04-29 07:06:43.112 App[10627:60b] _updatedObjects Count 0

我可以看到我正在获取一些对象的日志,但一切都是 null 或 0。我猜我的 MOC 是空白的。对象如何从mappingResultMOC

【问题讨论】:

【参考方案1】:

以下选项无法正常工作,因为 MOC 已保存,即使保存未传播到持久存储,因此您无法询问其更改。您可以使用相同的方法使用多个上下文,但是:

RestKit 能够使用 KVC 验证。因此,您可以在模型对象上实现许多方法并添加验证逻辑。这些方法使用新的传入数据调用,并且可以访问当前数据(self 的实例变量),因此您可以检查传入的值并检查是否需要:

    接受它 改变它 完全中止映射

见this ref。


您可以从 MOC 获得updatedObjects。获得更新的对象后,您可以获得每个对象的 changedValues。现在,使用该字典中的键,您可以使用 committedValuesForKeys: 获取以前保存的值。

现在您拥有进行比较所需的所有信息。您应该处理每个键并应用您想要的任何逻辑。作为处理的一部分,您可以将一些变量改回其保存的值,或使用refreshObject:mergeChanges: 重置整个对象。

在处理结束时,保存上下文。

您不应该使用多个不同的上下文来实现这一点,尽管您可能应该使用与标准主队列上下文不同的上下文。

【讨论】:

谢谢!我对这个问题做了更新,你能告诉我我是否走在正确的道路上吗?我遗漏了一些 b/c 的东西,一切都是 0 或 null。 你有没有updatedObjects 或者它是空的?可能是 MOC 已保存,但未传播到持久存储... 我添加了日志。更新对象为空。我得到了 28 个对象。我有 SQLite 管理器,但我没有看到任何添加到商店的内容。 这很烦人,1 分钟后我添加了一个完全不同的替代方法。 如果您使用 KVC 验证进行修改,那么它会在映射期间发生,RestKit 将保存。否则,使用saveToPersistentStore:(不是save:

以上是关于RESTKit:在覆盖之前将 GET 对象与本地持久化的对象进行比较的主要内容,如果未能解决你的问题,请参考以下文章

我可以防止 RestKit+CoreData 覆盖本地实体更改吗?

RestKit 在映射或实际插入 CoreData DB 之前比较本地对象和远程对象

iOS:RESTKit 与 CoreData 同步数据

在 Restkit 执行映射操作之前删除 Core data 中的现有对象

RestKit 将未嵌套关系映射到拥有对象

如何在通过 Core Data 保存我的 RestKit 托管对象之前对其进行修改?